try{} catch(…){} Exception handling options. /EHa vs /EHsc

本文探讨了C++中异常处理的不同方法,特别是在VC编译器下的表现差异。指出在Release模式下使用try{}

以前都是用try{} catch(…){}来捕获C++中一些意想不到的异常, 今天看了Winhack的帖子才知道,这种方法在VC中其实是靠不住的。例如下面的代码:

  1. try
  2. {
  3. BYTE*pch;
  4. pch=(BYTE*)00001234;//给予一个非法地址
  5. *pch=6;//对非法地址赋值,会造成Access Violation 异常
  6. }
  7. catch(...)
  8. {
  9. AfxMessageBox("catched");
  10. }

这段代码在debug下没有问题,异常会被捕获,会弹出”catched”的消息框。 但在Release方式下如果选择了编译器代码优化选项,则VC编译器会去搜索try块中的代码, 如果没有找到throw代码, 他就会认为try catch结构是多余的, 给优化掉。 这样造成在Release模式下,上述代码中的异常不能被捕获,从而迫使程序弹出错误提示框退出。

那么能否在release代码优化状态下捕获这个异常呢, 答案是有的。 就是__try, __except结构, 上述代码如果改成如下代码异常即可捕获。

  1. __try
  2. {
  3. BYTE*pch;
  4. pch=(BYTE*)00001234;//给予一个非法地址
  5. *pch=6;//对非法地址赋值,会造成Access Violation 异常
  6. }
  7. __except(EXCEPTION_EXECUTE_HANDLER)
  8. {
  9. AfxMessageBox("catched");
  10. }

但是用__try, __except块还有问题, 就是这个不是C++标准, 而是Windows平台特有的扩展。 而且如果在使用过程中涉及局部对象析构函数的调用,则会出现C2712的编译错误。 那么还有没有别的办法呢?

当然有, 就是仍然使用C++标准的try{}catch(..){}, 但在编译命令行中加入/EHa的参数。这样VC编译器不会把try catch模块给优化掉了。

/EHa means "Do the right thing, no matter what happens". /EHsc means "Take every shortcut you can find". There's a notable cost associated to exception handling, notably in 32-bit mode because of the cost of setting up the SEH chain. /EHsc is there to let you to tell the compiler "do the best you can".

http://social.msdn.microsoft.com/Forums/en/vclanguage/thread/80d7ae59-141c-4993-bd1f-6bcb72be000b

16:45:07: 为项目CircleFindDemo执行步骤 ... 16:45:07: 正在启动 "D:\QT\5.15.2\msvc2019_64\bin\qmake.exe" C:\Users\Administrator\Desktop\work\QTSamples\MVD_GeoFind\CircleFindDemo\CircleFindDemo.pro -spec win32-msvc "CONFIG+=debug" "CONFIG+=qml_debug" 16:45:07: The command "D:\QT\5.15.2\msvc2019_64\bin\qmake.exe C:\Users\Administrator\Desktop\work\QTSamples\MVD_GeoFind\CircleFindDemo\CircleFindDemo.pro -spec win32-msvc "CONFIG+=debug" "CONFIG+=qml_debug"" finished successfully. 16:45:07: 正在启动 "D:\program\visualstudio2022\program\VC\Tools\MSVC\14.44.35207\bin\HostX64\x64\nmake.exe" -f C:/Users/Administrator/Desktop/work/QTSamples/MVD_GeoFind/CircleFindDemo/build/Desktop_Qt_5_15_2_MSVC2019_64bit-Debug/Makefile qmake_all Microsoft (R) 程序维护实用工具 14.44.35213.0 版 版权所有 (C) Microsoft Corporation。 保留所有权利。 16:45:07: The command "D:\program\visualstudio2022\program\VC\Tools\MSVC\14.44.35207\bin\HostX64\x64\nmake.exe -f C:/Users/Administrator/Desktop/work/QTSamples/MVD_GeoFind/CircleFindDemo/build/Desktop_Qt_5_15_2_MSVC2019_64bit-Debug/Makefile qmake_all" finished successfully. 16:45:07: 正在启动 "D:\program\visualstudio2022\program\VC\Tools\MSVC\14.44.35207\bin\HostX64\x64\nmake.exe" D:\program\visualstudio2022\program\VC\Tools\MSVC\14.44.35207\bin\HostX64\x64\nmake.exe -f Makefile.Debug D:\QT\5.15.2\msvc2019_64\bin\uic.exe ..\..\mainwindow.ui -o ui_mainwindow.h cl -BxD:\QT\5.15.2\msvc2019_64\bin\qmake.exe -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -Zi -MDd -EHsc -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E D:\QT\5.15.2\msvc2019_64\mkspecs\features\data\dummy.cpp 2>NUL >debug\moc_predefs.h D:\QT\5.15.2\msvc2019_64\bin\moc.exe -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_DEPRECATED_WARNINGS -DQT_QML_DEBUG -DQT_AXCONTAINER_LIB -DQT_AXBASE_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB --compiler-flavor=msvc --include C:/Users/Administrator/Desktop/work/QTSamples/MVD_GeoFind/CircleFindDemo/build/Desktop_Qt_5_15_2_MSVC2019_64bit-Debug/debug/moc_predefs.h -ID:/QT/5.15.2/msvc2019_64/mkspecs/win32-msvc -IC:/Users/Administrator/Desktop/work/QTSamples/MVD_GeoFind/CircleFindDemo -IC:/Users/Administrator/Includes/Common/VisionDesigner -IC:/Users/Administrator/Includes/Common/MVDRenderControl -IC:/Users/Administrator/Includes/Algorithms -IC:/Users/Administrator/Desktop/work/QTSamples/MVD_GeoFind/CircleFindDemo/Includes -ID:/QT/5.15.2/msvc2019_64/include -ID:/QT/5.15.2/msvc2019_64/include/ActiveQt -ID:/QT/5.15.2/msvc2019_64/include/QtWidgets -ID:/QT/5.15.2/msvc2019_64/include/QtGui -ID:/QT/5.15.2/msvc2019_64/include/QtANGLE -ID:/QT/5.15.2/msvc2019_64/include/QtCore -I. -ID:\program\visualstudio2022\program\VC\Tools\MSVC\14.44.35207\include -ID:\program\visualstudio2022\program\VC\Tools\MSVC\14.44.35207\ATLMFC\include -ID:\program\visualstudio2022\program\VC\Auxiliary\VS\include -I"D:\Windows Kits\10\include\10.0.26100.0\ucrt" -I"D:\Windows Kits\10\\include\10.0.26100.0\\um" -I"D:\Windows Kits\10\\include\10.0.26100.0\\shared" -I"D:\Windows Kits\10\\include\10.0.26100.0\\winrt" -I"D:\Windows Kits\10\\include\10.0.26100.0\\cppwinrt" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" ..\..\mainwindow.h -o debug\moc_mainwindow.cpp cl -c -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -Zi -MDd -EHsc -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 /Fddebug\CircleFindDemo.vc.pdb -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_DEPRECATED_WARNINGS -DQT_QML_DEBUG -DQT_AXCONTAINER_LIB -DQT_AXBASE_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I..\..\..\CircleFindDemo -I. -IC:/Users/Administrator/Desktop/work/QTSamples/MVD_GeoFind/CircleFindDemo/../../../../../Includes/Common/VisionDesigner -IC:/Users/Administrator/Desktop/work/QTSamples/MVD_GeoFind/CircleFindDemo/../../../../../Includes/Common/MVDRenderControl -IC:/Users/Administrator/Desktop/work/QTSamples/MVD_GeoFind/CircleFindDemo/../../../../../Includes/Algorithms -I..\..\Includes -ID:\QT\5.15.2\msvc2019_64\include -ID:\QT\5.15.2\msvc2019_64\include\ActiveQt -ID:\QT\5.15.2\msvc2019_64\include\QtWidgets -ID:\QT\5.15.2\msvc2019_64\include\QtGui -ID:\QT\5.15.2\msvc2019_64\include\QtANGLE -ID:\QT\5.15.2\msvc2019_64\include\QtCore -Idebug -I. -I/include -ID:\QT\5.15.2\msvc2019_64\mkspecs\win32-msvc -Fodebug\ @C:\Users\ADMINI~1\AppData\Local\Temp\nm9FD2.tmp main.cpp C:\Users\Administrator\Desktop\work\QTSamples\MVD_GeoFind\CircleFindDemo\mainwindow.h(9): fatal error C1083: 无法打开包括文件: “MVDShapeCpp.h”: No such file or directory mainwindow.cpp ..\..\mainwindow.cpp(1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 C:\Users\Administrator\Desktop\work\QTSamples\MVD_GeoFind\CircleFindDemo\mainwindow.h(9): fatal error C1083: 无法打开包括文件: “MVDShapeCpp.h”: No such file or directory mvdrendercontrollib.cpp 正在生成代码... NMAKE : fatal error U1077: “cl -c -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -Zi -MDd -EHsc -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 /Fddebug\CircleFindDemo.vc.pdb -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DQT_DEPRECATED_WARNINGS -DQT_QML_DEBUG -DQT_AXCONTAINER_LIB -DQT_AXBASE_LIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I..\..\..\CircleFindDemo -I. -IC:/Users/Administrator/Desktop/work/QTSamples/MVD_GeoFind/CircleFindDemo/../../../../../Includes/Common/VisionDesigner -IC:/Users/Administrator/Desktop/work/QTSamples/MVD_GeoFind/CircleFindDemo/../../../../../Includes/Common/MVDRenderControl -IC:/Users/Administrator/Desktop/work/QTSamples/MVD_GeoFind/CircleFindDemo/../../../../../Includes/Algorithms -I..\..\Includes -ID:\QT\5.15.2\msvc2019_64\include -ID:\QT\5.15.2\msvc2019_64\include\ActiveQt -ID:\QT\5.15.2\msvc2019_64\include\QtWidgets -ID:\QT\5.15.2\msvc2019_64\include\QtGui -ID:\QT\5.15.2\msvc2019_64\include\QtANGLE -ID:\QT\5.15.2\msvc2019_64\include\QtCore -Idebug -I. -I/include -ID:\QT\5.15.2\msvc2019_64\mkspecs\win32-msvc -Fodebug\ @C:\Users\ADMINI~1\AppData\Local\Temp\nm9FD2.tmp”: 返回代码“0x2” Stop. NMAKE : fatal error U1077: “D:\program\visualstudio2022\program\VC\Tools\MSVC\14.44.35207\bin\HostX64\x64\nmake.exe -f Makefile.Debug”: 返回代码“0x2” Stop. 16:45:10: The command "D:\program\visualstudio2022\program\VC\Tools\MSVC\14.44.35207\bin\HostX64\x64\nmake.exe" terminated with exit code 2. 16:45:10: Error while building/deploying project CircleFindDemo (kit: Desktop Qt 5.15.2 MSVC2019 64bit) 16:45:10: When executing step "Make" 16:45:10: Elapsed time: 00:03. 这个代码也是
最新发布
11-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值