VS2017程序终止报错‘abort() has been called’原因排查
问题解答:析构函数异常与
abort()调用的关联 首先直接给结论:你的程序触发abort()退出,确实是析构函数抛出异常导致的,下面详细拆解原因:
1. C++标准的明确规定
C++标准里有一条关键规则:当程序处于栈展开(也就是因为某个异常被抛出,系统正在销毁栈上的局部对象以回退调用栈的过程)时,如果某个析构函数抛出了未被捕获的异常,程序会直接调用std::terminate()。而默认情况下,std::terminate()的行为就是调用abort(),这就是你看到报错的根源。
哪怕你的析构函数里写了try-catch块,也有两种情况会触发问题:
- 如果你的
catch块处理完异常后重新抛出了异常(比如写了throw;),而此时程序正处于栈展开阶段,一样会触发std::terminate()。 - 或者你的
catch块没有捕获到抛出的异常类型(不过你这里抛的是int,catch的也是int,这种情况概率极低)。
2. VS2012能正常运行的原因
VS2012是比较老旧的编译器,它对C标准的兼容性并不严格,在析构函数异常的处理上做了非标准的宽松处理,没有严格遵循标准触发std::terminate()。但这种行为是特定旧版本编译器的特例,并不符合C标准,在新版本的VS(比如VS2019/2022)或者其他标准兼容的编译器(比如GCC、Clang)上,都会触发abort()。
3. 正确的处理方式
永远不要让析构函数抛出未被捕获的异常,如果在析构函数里必须执行可能抛异常的操作,一定要在析构函数内部完全处理掉:
~Txn() { try { cout << "in destructor" << endl; throw 10; } catch(int i) { // 在这里完全处理异常,比如记录日志,不要重新抛出 cout << "Caught exception in destructor: " << i << endl; } // 确保没有任何异常逃出析构函数 }
内容的提问来源于stack exchange,提问作者novice




