前几天从网上下载了一份网友用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安装目录下的 mkspecs\features\win32\default_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:\Qt\4.8.3\bin\qmake.exe" E:\QtWork\TryCatchTest\TryCatchTest.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());
} else if(ex == EXCEP_TWO )
{
QMessageBox::information(NULL, "Information", QString::number());
}
}
try {
int i = ;
i = i >> ;
if (i==) {
i = /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功能的原因。

Qt try catch排错历程——C++的异常对除零不起作用的更多相关文章

  1. 如何用Windbg找到被catch住的C++的异常

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:如何用Windbg找到被catch住的C++的异常.

  2. HTTP Error 500.0 - ANCM In-Process Handler Load Failure 排错历程

    先上报错图 环境 Window Server 2008 r2 netcore 2.2 排错历程 看到这个错 我第一个想到netcore 安装问题 先检查了下环境 发现没问题 我排查了下应用池 确定是无 ...

  3. try{}catch(e){}不能捕获到异常

    只能捕获到ReferenceError异常,I don't know why. try{ aa();//这是一个未被定义的方法 }catch(e){ if(e instanceof Reference ...

  4. 排错:Windows系统异常导致Filebeat无法正常运行

    Windows 下Filebeat排错Case实例一份,请查收. 问题描述: Windows Server下Filebeat Agent服务无法正常启动,导致网络数据打点无法正常进行,影响大范围用户网 ...

  5. java异常处理 throw RuntimeException时不需要同时方法中声明抛出throws 异常等待调用者catch进行捕获 子父类异常问题

    package com.swift.exception1; public class Demo_Exception { public static void main(String[] args) { ...

  6. c#catch循环内捕获到异常继续循环

    一,如果我们将异常而不影响循环,如下代码: using System; using System.Collections.Generic; using System.Linq; using Syste ...

  7. Qt、Qte与Qtopia(Qt嵌入式的发展历程)

    Qt的授权是分为两条线,商业版和开源版.如果使用商业版的Qt,那么开发出的程序可以是私有的和商业的:如果使用的是开源版的Qt,由于其使用的是GPL协议,那么可发出的程序也必须是GPL的.不过自从qt ...

  8. Halcon异常(C++)不起作用

    现象 Halcon导出的C++程序,try catch不到异常.在Halcon下可以正常Catch到异常.  C++代码:try{   tuple_max(hv_Length, &hv_Max ...

  9. 异常-finally关键字的特点及作用

    package cn.itcast_07; import java.text.ParseException; import java.text.SimpleDateFormat; import jav ...

随机推荐

  1. keil Ax51中条件编译指令IF与$IF的区别

    keil A51中条件编译指令IF与$IF的区别:1.IF和$IF是不等价的,不要混淆了;2.带前缀$的条件编译$IF用法:(汇编器指示命令Assembler Directive)只能用来测试由$SE ...

  2. QDialog 模态对话框与事件循环(exec其实就是调用了show和eventLoop.exec)

    起源 qtcn中文论坛中有网友问到: 假设程序正常运行时,只有一个简单的窗体A,此时只有一个GUI主线程,在这个主线程中有一个事件循环处理窗体上的事件.当此程序运行到某阶段时,弹出一个模态窗体B(书上 ...

  3. BZOJ2751: [HAOI2012]容易题(easy)

    2751: [HAOI2012]容易题(easy) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 872  Solved: 377[Submit][S ...

  4. 转:String.Empty、string=”” 和null的区别

    原文地址:http://www.cnblogs.com/fanyong/archive/2012/11/01/2750163.html String.Empty是string类的一个静态常量: Str ...

  5. NOI2012 美食节

    http://www.lydsy.com/JudgeOnline/problem.php?id=2879 费用流. 我们发现,每个厨师做的倒数第k道菜对总等待时间的贡献为k*做这道菜的时间. 将每个厨 ...

  6. sphinx全文检索之PHP使用教程

    以上一篇的email数据表为例: 数据结构: 01.CREATE TABLE email ( 02.emailid mediumint(8) unsigned NOT NULL auto_increm ...

  7. [转]notifyDataSetChanged() 动态更新ListView

    有时候我们需要修改已经生成的列表,添加或者修改数据,notifyDataSetChanged()可以在修改适配器绑定的数组后,不用重新刷新Activity,通知Activity更新ListView.今 ...

  8. SWTBOK測试实践系列(4) -- 软件測试技术的黑白之道

    白盒測试和黑盒測试往往是项目中最受争议的两种測试类型,每一个人偏爱各不同.现实生活中行业人员大多喜欢白盒測试而忽视黑盒測试,那么项目中又应该怎样平衡这两类測试呢?我们先来看两个案例. 案例一: 某移动 ...

  9. T4文本模板

    <#...#> 可以包含语句 <#=...#>  用于表达式,提供“输出”操作 <#+ ...> 使用类功能控制块向文本模板添加方法.属性.字段,必须作为文件中最后 ...

  10. VS2015 新Web项目(C#6)出现CS1617异常的解决

    VS2015 新Web项目(C#6)出现CS1617错误的解决 VS2015新增了对C#6的支持. 在新的Web项目模板中通过引入nuget包Microsoft.CodeDom.Providers.D ...