0

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

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

我的问题logic_errorA::doSomething(). 有没有办法恢复它?

#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)
4

1 回答 1

1

编辑:在http://www.compileonline.com上进行试验我也发现观察到的行为很奇怪。看起来 terminate() 将在不同的线程或异步上调用,而主线程提前执行,甚至在系统注意到它应该停止之前破坏了 A(1)。

重新阅读 C++03 它仍然声明相同,到 15.5.1p1b3 必须调用终止,并且 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#47SO 线程,了解如果您编写这样的代码会发生什么。

总结:语言规则是,如果成功抛出异常(它被复制并开始堆栈展开),并且在它被捕获之前抛出另一个异常,则调用 terminate()。由于不太可能以您想要的方式终止,请考虑重新排列代码以避免此问题。

于 2013-06-09T23:52:38.927 回答