You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动