当函数带两个异常退出时,原始异常发生了什么?

when function exits with 2 exceptions, what happens to the original exception

本文关键字:异常 退出 发生了 什么 原始 两个 函数      更新时间:2023-10-16

注意:我在redhat linux 6.3上使用gcc 4.4.7。下面的例子中的问题是关于GCC如何处理从A::doSomething()抛出的第一个异常,而不是关于是否应该从析构函数抛出异常。

在下面的代码中,A::doSomething()函数退出,logic_error函数有2个异常。析构函数~A()中的第二个logic_error似乎覆盖了A::doSomething()中的logic_error。程序的输出如下所示:

我的问题是A::doSomething()抛出的logic_error发生了什么。有办法恢复吗?

#include <iostream>
#include <stdexcept>
#include <sstream>
using namespace std;
class A
{
public:
A(int i):x(i) {};
void doSomething();
~A() {
    cout << "Destroying " << x << endl;
    stringstream sstr;
    sstr << "logic error from destructor of " << x << " ";
    throw logic_error(sstr.str());
    }
private:
int x;
};
void A::doSomething()
{
A(2);
throw logic_error("from doSomething");
}

int main()
{
A a(1);
try
{
    a.doSomething();
}
catch(logic_error & e)
{
    cout << e.what() << endl;
}
return 0;
}

输出是:

Destroying 2
logic error from destructor of 2
Destroying 1
terminate called after throwing an instance of 'std::logic_error'
what():  logic error from destructor of 1
Aborted (core dumped)

编辑:在http://www.compileonline.com上进行实验,我也发现观察到的行为很奇怪。看起来好像terminate()会在另一个线程或异步上被调用,而主线程在系统注意到应该停止之前执行,甚至破坏了a(1)。

重新阅读c++ 03,它仍然声明相同,到15.5.1p1b3必须调用terminate,到p2不允许进一步的任何操作。GCC的行为在这里显得不一致。

在http://coliru.stacked-crooked.com/上更新的GCC输出是:

Destroying 2
terminate called after throwing an instance of 'std::logic_error'
  what():  logic error from destructor of 2 

这是预期的(没有最后两行,但我们可以认为是在terminate()调用之后的额外信息)。


一致性实现的理论:

阅读GOTW#47和SO线程,了解如果您编写这样的代码会发生什么。

作为总结:语言规则是,如果异常被成功抛出(它被复制并开始堆栈展开),并且在它被捕获之前抛出另一个异常,则调用terminate()。

如果以不太可能的方式结束,请考虑重新排列代码以避免此问题。