• Qt try catch排错历程——C++的异常对除零不起作用


       前几天从网上下载了一份网友用Qt写的作品,打开时发现它是用VS2010写的,而我机器上只有VS2008,倒腾了半天最终没能用VS2008打开,而自己又不想再安装VS2010。还好在工程中有.pro文件,我只好用QtCreator打开了它。但是在编译的时候出现了这个错误提示:exception handling disabled, use -fexceptions to enable,因此也就有了以下的排错经历。
        为了找到问题的根源,我在两个环境下专门建了一个类似的小工程TryCatchTest。
        环境一:VS2008 + Qt4.8.3-vs2008 + Qt Visual Studio Add-in1.1.10
        环境二:Qt Creator 2.6.0 + Qt4.8.3-mingw + mingw32 4.6.2
        代码如下:

    1. #include <QCoreApplication> 
      enum Excep 

      EXCEP_ONE, 
      EXCEP_TWO 
      }; 

      void throwFun() 

        throw EXCEP_ONE; 


      int main(int argc, char *argv[]) 

        QCoreApplication a(argc, argv); 
        try 
        { 
          throwFun(); 
        } 
        catch(Excep ex) 
        { 
          if(ex == EXCEP_ONE ) 
          { 
           //ToDo.... 
          } 
        } 
      return a.exec(); 
      }


        
        在VS环境下编译后,一点问题都没有,甚至连警告都没有。这说明问题出在编译器上,而且是编译器的配置问题。但是怎么对mingw-g++编译器进行配置呢?于是我在网上搜了下错误提示信息,找到了一篇博客http://blog.csdn.net/garybook/article/details/7764200。但是很遗憾这篇博客所解决的问题并不是Qt的,而是解决安卓的NDK问题的。但其中的内容给了我一点启发。文章中说此问题的出现是编译器的异常捕获被禁用了,需要在Android.mk文件中开启。在Android.mk文件中添加:LOCAL_CPPFLAGS += -fexceptions就可以了。于是我依葫芦画瓢的在TryCatchTest.pro文件中添加了一行CONFIG += -fexceptions,但是错误依旧。
        由于在Qt Creator中仅执行qmake时是没问题的,而且还生成了三个文件Makefile、Makefile.Debug、Makefile.Release。在Makefile.Debug和Makefile.Release文件中我找到了以下这行:
    CXXFLAGS      = -O2 -Wall -Wextra -fno-exceptions -fno-rtti $(DEFINES)
    那么这一行是怎么生成的,也就是说qmake.exe到底是怎么工作的呢。为了搞清楚这个疑惑,我自己编译了qmake的源码,并进行了一系列的跟踪调试(编译qmake的过程也困难重重,其又可另写篇日志了,此处不再赘述)。
        对qmake.exe进行跟踪调试后,终于发现了配置-fno-exceptions的地方。它是在Qt安装目录下的 mkspecsfeatureswin32default_pre.prf文件中。这个文件中有这样一句:
    CONFIG = rtti_off exceptions_off stl_off incremental_off thread_off windows $$CONFIG
    随之又跟踪到了mkspecs/features/win32/exceptions_off.prf文件,在这个文件中看到了这样一句:
    CONFIG  -=  exceptions。
    于是我在TryCatchTest.pro文件中添加了一行 CONFIG += exceptions(也可以写成CONFIG  -= exceptions_off)。就这样问题完美解决了。
        其实如果细心的话,我们可以在上面提到的Makefile文件中看到default_pre.prf、exceptions_off.prf文件的踪迹。
        以下是Makefile文件中的部分片断:

    1. ...... 
      Makefile: ../TryCatchTest/TryCatchTest.pro 
      ../../Qt/4.8.3/mkspecs/win32-g++/qmake.conf  
      ../../Qt/4.8.3/mkspecs/features/device_config.prf  
      ../../Qt/4.8.3/mkspecs/features/qt_functions.prf  
      ../../Qt/4.8.3/mkspecs/features/qt_config.prf  
      ../../Qt/4.8.3/mkspecs/features/exclusive_builds.prf  
      ../../Qt/4.8.3/mkspecs/features/default_pre.prf  
      ../../Qt/4.8.3/mkspecs/features/win32/default_pre.prf  
      ../../Qt/4.8.3/mkspecs/features/debug.prf  
      ../../Qt/4.8.3/mkspecs/features/debug_and_release.prf  
      ../../Qt/4.8.3/mkspecs/features/default_post.prf  
      ../../Qt/4.8.3/mkspecs/features/win32/default_post.prf  
      ../../Qt/4.8.3/mkspecs/features/win32/console.prf  
      ../../Qt/4.8.3/mkspecs/features/declarative_debug.prf  
      ../../Qt/4.8.3/mkspecs/features/warn_on.prf  
      ../../Qt/4.8.3/mkspecs/features/qt.prf  
      ../../Qt/4.8.3/mkspecs/features/win32/thread.prf  
      ../../Qt/4.8.3/mkspecs/features/moc.prf  
      ../../Qt/4.8.3/mkspecs/features/win32/stl_off.prf  
      ../../Qt/4.8.3/mkspecs/features/win32/exceptions_off.prf  
      ../../Qt/4.8.3/mkspecs/features/win32/rtti_off.prf  
      ../../Qt/4.8.3/mkspecs/features/resources.prf  
      ../../Qt/4.8.3/mkspecs/features/uic.prf  
      ../../Qt/4.8.3/mkspecs/features/include_source_dir.prf 
      ......



        从上面的片断可以看出,编译器的配置信息都是在features文件夹中的xxx.prf中,其实如果再仔细点的话就会发现Qt Creator启动qmake时传了两个特殊的参数,-spec和win32-g++。下面是Qt Creator在编译信息显示框中启动qmake的完整命令:

    1. "C:Qt4.8.3inqmake.exe" E:QtWorkTryCatchTestTryCatchTest.pro -r -spec win32-g++ "CONFIG+=debug" "CONFIG+=declarative_debug"



        这两个特殊参数的玄机我就不多说了。

        后记:
        写这篇日志的目的主要在于记录这个过程,对于我这种新手文笔比不了那些博客大牛,所涉及的技术知识也许在高手眼里就根本不值得一提。但是在解决这个问题的过程中使我多少了解了些qmake的机制,这无疑是一种收获一种提升!

    http://www.qtcn.org/bbs/apps.php?q=diary&a=detail&did=1197&uid=123665

    -------------------------------------------------------------------------------------------------

    但是感觉C++的异常对除零不起作用,比如:

    #include "mainwindow.h"
    #include <QApplication>
    #include <QMessageBox>
    
    enum Excep
    {
    EXCEP_ONE,
    EXCEP_TWO
    };
    
    void throwFun()
    {
      throw EXCEP_TWO;
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        try
        {
          //throwFun();
        }
        catch(Excep ex)
        {
            if(ex == EXCEP_ONE )
            {
                QMessageBox::information(NULL, "Information", QString::number(1));
            } else if(ex == EXCEP_TWO )
            {
                QMessageBox::information(NULL, "Information", QString::number(2));
            }
        }
        try {
            int i = 1;
            i = i >> 1;
            if (i==0) {
                i = 1/i;
                QMessageBox::information(NULL, "Information", QString::number(i));
            }
        }
        catch(int e)
        {
             QMessageBox::information(NULL, "Information", QString::number(e));
        }
        MainWindow w;
        w.show();
    
        return a.exec();
    }

    每次都崩溃!!

    原因是C++离底层太近了,相当于直接产生了汇编引起的CPU错误,除非使用操作系统提供的功能(比如SEH),否则C++自身无法防止它的崩溃!这也是C++默认不开启try catch功能的原因。

  • 相关阅读:
    AS400小结(2)
    java循环链表
    RPG程序中一些小结
    学习AS400心得体会
    Vue学习二
    Vue学习一
    VC视图的多页打印(转)
    MFC对象拖拽功能(不只是文件拖拽)(转)
    Silverlight如何显示、输入上标和下标?
    【2011】Google Maps API3
  • 原文地址:https://www.cnblogs.com/findumars/p/4898360.html
Copyright © 2020-2023  润新知