如何检测析构函数期间异常是否处于活动状态?

发布于 2024-12-13 00:05:42 字数 117 浏览 4 评论 0原文

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

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

In C++, how can I detect in the body of my destructor whether the stack is being unwound due to an exception being thrown? Once detected, can I get a reference to the active exception?

I ask because I'd like to add some debugging code that explains why a certain situation may arise and whether it is due to exceptions or not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

长发绾君心 2024-12-20 00:05:42

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 处理程序中的异常,或者其 catch 处理程序已调用您的异常。它不会重新抛出未捕获的异常。

std::uncaught_exception tells you whether the stack is being unwound due to an exception being thrown, which is what you asked.

However, it doesn't tell you what you probably want to know: whether the object whose destructor you call it from, is in the part of the stack that's being unwound, or the part of the stack that's being destroyed normally due to non-exceptionally exiting a scope beneath some other destructor that is part of the unwind:

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.
}

Contrary to what DeadMG and Xeo say, you cannot get a reference to an exception that has not been caught. throw with no operand rethrows the "currently handled exception", that is to say an exception whose catch-handler you are in, or whose catch-handler has called you. It does not rethrow an uncaught exception.

冬天旳寂寞 2024-12-20 00:05:42

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() 跟踪调用代码时未捕获的异常的数量。更多信息可以在其 cppreference 页面上找到。

What about C++17's new std::uncaught_exceptions()? I think you can build a code that looks like this:

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
        }
    }
};

In this case, std::uncaught_exceptions() tracks the number of uncaught exceptions by the time the code is called. More info can be found on its cppreference page.

走走停停 2024-12-20 00:05:42

有一个 std::uncaught_exception() 函数。然而,要尝试访问异常对象,您可以做的唯一有用的事情就是重新抛出它并尝试捕获它。一般来说,您不应该从任何析构函数中抛出异常。

There is a std::uncaught_exception() function. However, about the only useful thing you can do to attempt to gain access to the exception object is rethrow it and try to catch it. You should never throw exceptions from any destructor, in general.

萤火眠眠 2024-12-20 00:05:42

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

不是。

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

不。

In C++, how can I detect in the body of my destructor whether the stack is being unwound due to an exception being thrown?

Not.

Once detected, can I get a reference to the active exception?

No.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文