静态初始化抛异常:局部静态对象构造异常为何可被捕获?
C++局部静态对象构造异常的标准规定与实际行为
问题背景
cppreference提到静态或线程局部对象构造期间抛出异常会调用terminate(),但测试函数内的局部静态变量时,却能正常捕获其构造函数抛出的异常,且MSVC、clang++、g都支持这种行为,需要明确C标准对此的具体规定。
C++标准的明确规定
- 函数内的局部静态对象:这类对象的初始化发生在首次执行到其声明语句时,属于当前函数调用流程的一部分。如果构造函数抛出异常,异常会沿着调用栈向上传播,完全可以被当前作用域内的
try-catch块捕获,不会直接触发terminate()。 - 命名空间作用域的全局静态对象/线程局部对象:这类对象的初始化发生在程序启动阶段(全局静态)或线程启动阶段,此时没有有效的异常处理上下文(不存在包裹初始化过程的
try-catch),所以一旦构造函数抛出异常,会直接调用terminate()终止程序——这正是cppreference所描述的场景。 - 析构阶段的异常:静态存储期对象的析构发生在
main()退出后(全局静态)或线程退出后(线程局部),此时同样没有可用的异常处理上下文,若析构函数抛出异常,必然触发terminate(),这和你的理解一致。
验证代码
以下代码在主流编译器中均可正常捕获异常并输出错误信息:
#include <iostream> using namespace std; int main() { struct S { S() { throw invalid_argument( "hello world" ); }; }; try { static S s; } catch( exception const &exc ) { cout << exc.what() << endl; } }
内容的提问来源于stack exchange,提问作者Edison von Myosotis
相关产品推荐
相关产品推荐

