青春时代是一个短暂的美梦,当你醒来时,它早已消失得无影无踪了。
 
昨日:篇  今日:篇   总帖:篇   会员:
admin
夜月琉璃Lv18   
windows程序崩溃对话框和异常处理     
原文地址:http://blog.csdn.net/ibingow/article/details/7104346


 经常碰到某些程序崩溃时弹出带红色叉叉的错误窗口或者是叫你选择调试或关闭的窗口,很碍眼。不过平时也没去理它,点掉就好。

ImageImage


    今天客户反映我们的程序崩溃后就起不来了,其实我们为了方便无人化管理,做了一个守护进程。如果程序异常退出就会重启那个程序,这在linux下没问题,程序崩溃了就直接退出返回非零值,但是window就bug了,搞不好就给你弹出个错误对话框,你不点掉其实程序就没退出,守护进程就不知道这个程序是否崩溃,于是这个程序就永远死在那个窗口上了。现在这不仅碍眼,还碍事!于是着手摆平之。

    先是晚上搜到可以修改注册表来组织程序或系统的弹出对话框,参考:http://technet.microsoft.com/en-us/library/cc976167.aspx。不过这不可行,我们只是希望我们的程序不会弹出对话框,尽量少改系统的。而且试了下发现还是会弹出来,就是那个werfault.exe进程,xp下可能不会。算了,这条路不走了。
    用代码肯定也有办法解决。你看人家qq什么的奔溃了有弹出的都是自家的温馨提示,我们不需要温馨提示,只要返回非零值就好。
    万能的Google一下子就搜出结果来了。原来Microsoft对c和c++进行了扩展,支持异常处理,而且貌似标准c++里的异常处理也是它的一个封装。Microsoft的异常处理函数是__try,__except

先试了这么个简单的例子

#include <windows.h>  
#include <excpt.h>  
#include <stdio.h>  
  
#define  CRASH_SILENTLY 1  
#if defined(_MSC_VER) && CRASH_SILENTLY  
#include <excpt.h>  
#define Q_TRY_BEGIN     __try {  
#define Q_TRY_END       }  
//EXCEPTION_EXECUTE_HANDLER  
#define Q_EXCEPT        __except(EXCEPTION_EXECUTE_HANDLER) { \  
    printf("Shit happens!\n");fflush(NULL); \  
    return 1;}  
#else  
#define Q_TRY_BEGIN  
#define Q_TRY_END  
#define Q_EXCEPT  
#endif  
  
int main(int, char**)  
{  
Q_TRY_BEGIN  
    int *a = 0;  
    *a = 0;  
Q_TRY_END  
Q_EXCEPT  
    printf("Exiting 0...\n");  
    fflush(NULL);  
    return 0;  
}  

    如果把CRASH_SILENTLY定义为0,那么在程序崩溃就会弹出对话框,设为一就只打印Shit happens!然后就返回。
    __except的参数有三种,详细内容见http://msdn.microsoft.com/en-us/library/s58ftw19%28v=vs.80%29.aspx,我就不抄了。
    其实为什么系统会弹出这么一个对话框呢?其实在vc运行库中顶层函数也用了__try, __except的异常捕获机制。不知您看了__except的参数了没,我的示例程序里是EXCEPTION_EXECUTE_HANDLER,表示异常被识别,就在__except后面的代码段进行异常处理。如果是EXCEPTION_CONTINUE_SEARCH,那么异常会继续被派发到外层,这最外层就是vc库,vc库它的处理手段就是碍眼又碍事的对话框!

    上面这个程序只是演示用的,很简单。然后我就满怀希望地对公司的程序也做了类似的处理,然后悲剧发生了,竟然编译都通不过!编译错误是C2712:cannot use __try in functions that require object unwinding。于是又google了一番。msdn真的很棒,资料丰富,这下有时msdn上的方法解决的。详见http://msdn.microsoft.com/en-us/library/xwtb73ad%28VS.80%29.aspx
    With /EHsc, a function with structured exception handling cannot have objects that require unwinding (destruction).
    我们的程序里出现了有析构函数的对象,同时编译参数又有/EHsc,于是出现编译错误了。可以参考下这篇文章http://se.csai.cn/ExpertEyes/No163.htm
    作为一个例子,如果我们把上面的程序改成下面的就可能出现上述问题

class Shit {  
public:  
    Shit() {}  
    ~Shit() {}  
  
};  
  
int main(int, char**)  
{  
Q_TRY_BEGIN  
    Shit s;  
    int *a = 0;  
    *a = 0;  
Q_TRY_END  
Q_EXCEPT  
    printf("Exiting 0...\n");  
    fflush(NULL);  
    return 0;  
}  
    msdn提出3种方案,允许我复制下
    Move code that requires SEH to another function.
    Rewrite functions that use SEH to avoid the use of local variables and parameters that have destructors. Do not use SEH in constructors or destructors.
    Compile without /EHsc.
    显然前两种办法对代码改动太大了,不可取,那么就去掉/EHsc吧。由于我是用Qt写程序,有些编译选项都是默认设好的,我在pro文件里尝试定义QMAKE_CXXFLAGS竟然无效,不是很清楚为什么。一般是在qmake.config和prf文件里里可以找到。qmake.conf里找到相关的两行

QMAKE_CXXFLAGS_STL_ON   = -EHsc  
QMAKE_CXXFLAGS_EXCEPTIONS_ON = -EHsc  
在我们工程文件里直接设这两个为空竟然可以。后来又看了下Makefile,发现生成Makefile会依赖exceptions.prf, stl.prf,而这两个会加入上面两个变量,比如stl.prf:

CONFIG -= stl_off  
QMAKE_CFLAGS *= $QMAKE_CFLAGS_STL_ON  
QMAKE_CXXFLAGS *= $QMAKE_CXXFLAGS_STL_ON 
于是在工程文件中加入

CONFIG -= exceptions stl  
或者

CONFIG += exceptions_off stl_off  
就解决问题了,而且比之前的方法优雅。看看Makefile里相关代码变成了

$(QMAKE) -spec ..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\default CONFIG+=release -o Makefile pvplayer.pro  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\qconfig.pri:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\modules\qt_webkit_version.pri:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\qt_functions.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\qt_config.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\exclusive_builds.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\default_pre.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\win32\default_pre.prf:  
..\config.pri:  
..\pvcommon\pvcommon.pri:  
..\config.pri:  
..\log4qt\log4qt.pri:  
..\config.pri:  
..\qextserialport\qextserialport.pri:  
..\config.pri:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\release.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\debug_and_release.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\default_post.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\win32\default_post.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\win32\rtti.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\shared.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\win32\embed_manifest_exe.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\win32\embed_manifest_dll.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\warn_on.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\qt.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\win32\thread.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\moc.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\win32\windows.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\win32\stl_off.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\win32\exceptions_off.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\resources.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\uic.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\yacc.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\lex.prf:  
..\..\..\..\QtSDK\Desktop\Qt\4.7.4\msvc2008\mkspecs\features\incredibuild_xge.prf:  
e:\QtSDK\Desktop\Qt\4.7.4\msvc2008\lib\qtmain.prl:  
    好,至此已经把弹出对话框的问题解决了。不过还值得深入研究,目前只是做到了会用的程度。还有就是linux下或其他平台上有无类似处理还没调查。应该也有,因为最近linux下的thunderbird一启动就崩溃,弹出对话框。有空继续研究。

参考文献:
http://msdn.microsoft.com/en-us/library/s58ftw19%28v=vs.80%29.aspx
http://msdn.microsoft.com/en-us/library/xwtb73ad%28VS.80%29.aspx
Use /EHa if you want to catch an exception raised with something other than a throw.
http://msdn.microsoft.com/en-us/library/1deeycx5%28VS.80%29.aspx
http://blog.csdn.net/bichenggui/article/details/4536534
http://se.csai.cn/ExpertEyes/No163.htm

 0  已被阅读了121次  楼主 2018-01-14 20:21:02
回复列表

回复:windows程序崩溃对话框和异常处理

桂公网安备 45010302000666号 桂ICP备14001770-3号
您的IP:54.160.153.233,2018-02-26 09:19:54,Processed in 1.07812 second(s).
免责声明: 本网不承担任何由内容提供商提供的信息所引起的争议和法律责任。
Powered by HadSky 5.4.1