前言
作业这几年在项目中用到c++ try…catch…的场景不多,自己一向以为try…catch…很简单,一目了然。但是直到最近在项目中用了一次try…catch…才发现自己之前的理解是片面的。。。
一、问题
#include <iostream>
using namespace std;
int main()
{
try {
*((unsigned int*)0) = 0xDEAD;
} catch (...) {
cout << "exception caught!";
}
return 0;
}
这段代码中的*((unsigned int*)0) = 0xDEAD;
能被catch住而且输出”exception caught!”吗?
二、测验
1.Build with Visual Studio on Windows
用Visual Studio编译执行的结果是正常输出”exception caught!”。
exception caught!
2.Build with g++ on Ubuntu
用g++编译执行的结果是程序反常退出。
Segmentation fault (core dumped)
三、解惑
这段代码存在对不合法地址的访问,这种类型的exception在C++规范里面是不支持被try…catch…捕获的,C++规范里面的try…catch…主要是为了捕获程序throw
出来的exception。所以Ubuntu上面g++编译的程序行为是符合C++规范的。
那么Windows上面用Visual Studio编译出来的程序为什么能够捕获反常呢?答案在微软的官方文档中能够找到:/EH (Exception handling model).
a
Enables standard C++ stack unwinding. Catches both structured (asynchronous) and standard C++ (synchronous) exceptions when you use catch(...) syntax. /EHa overrides both /EHs and /EHc arguments.
s
Enables standard C++ stack unwinding. Catches only standard C++ exceptions when you use catch(...) syntax. Unless /EHc is also specified, the compiler assumes that functions declared as extern "C" may throw a C++ exception.
c
When used with /EHs, the compiler assumes that functions declared as extern "C" never throw a C++ exception. It has no effect when used with /EHa (that is, /EHca is equivalent to /EHa). /EHc is ignored if /EHs or /EHa aren't specified.
应该是因为Visual Studio用了默许参数/EHa
所以能够捕获结构化反常。我试过加编译参数/EHs
最终得到和Ubuntu上g++相同的结果。关于微软的结构化反常这里不做展开,能够参阅Structured Exception Handling (C/C++)
总结
之前一向以为c++ try…catch…能够捕获到不同类型的exception,实际上try…catch…主要针对的是throw
抛出的反常。关于其他类型的反常想要捕获的话不同渠道有不同的完成,比如Windows渠道的结构化反常机制,Linux渠道的信号机制。