如何检测在析构过程中异常是否处于活动状态

How can I detect whether an exception is active during destructor?

本文关键字:异常 过程中 是否 活动状态 析构 何检测 检测      更新时间:2023-10-16

在c++中,如何在析构函数体中检测堆栈是否由于抛出异常而展开?一旦检测到,我可以获得对活动异常的引用吗?

我问这个问题是因为我想添加一些调试代码,解释为什么会出现某种情况,以及是否由于异常。

std::uncaught_exception告诉您是否由于抛出异常而展开堆栈,这是您所要求的。

然而,它并没有告诉你你可能想知道的:你调用它的析构函数的对象是在被展开的堆栈部分,还是在正常被取消的堆栈部分,因为非异常地退出了位于展开的其他析构函数下的作用域:

struct A {
    ~A();
};
struct B {
    ~B();
}
int main() {
    try {
        A a;
        throw 1;
    } catch(...) {}
}
A::~A() {
    std::uncaught_exception(); // true
    B b;
}
B::~B() {
    std::uncaught_exception(); // also true, but "b" isn't being "unwound",
      // because ~A() returned, it didn't throw.
}

与DeadMG和Xeo所说的相反,您无法获得对未被捕获的异常的引用。没有操作数的throw重新抛出"当前处理的异常",也就是说,您所在的catch-handler或其catch-handler调用了您的异常。它不会重新抛出未捕获的异常。

c++ 17的新std::uncaught_exceptions()呢?我认为你可以编写这样的代码:

class ExceptionSentinel
{
    int prev_uncaught;
public:
    ExceptionSentinel() : prev_uncaught(std::uncaught_exceptions()) {}
    ~ExceptionSentinel()
    {
        int cur_uncaught = std::uncaught_exceptions();
        if (cur_uncaught > prev_uncaught)
        {
            // ... ExceptionSentinel is being destructed by an stack unwinding process
        }
        else
        {
            // ... Normal destruction of ExceptionSentinel
        }
    }
};

在本例中,std::uncaught_exceptions()在调用代码之前跟踪未捕获异常的数量。

有一个std::uncaught_exception()函数。但是,要尝试访问异常对象,您可以做的唯一有用的事情是重新抛出它并尝试捕获它。一般情况下,永远不要从析构函数抛出异常。

在c++中,如何在析构函数体中检测堆栈是否由于抛出异常而展开?

一旦检测到,我可以得到对活动异常的引用吗?