c++ 如何在解卷期间获得抛出的异常?

toe95027  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(114)

考虑以下简单示例:

#include <exception>
#include <iostream>

class Foo {
    public:
~Foo() {
     std::exception_ptr ptr = std::current_exception();
     if(ptr) {
        std::cout << "Stack unwinding due to exception";
     }
     std::cout << "Number of uncaught exceptions: " << std::uncaught_exceptions() << "\n";

}
};

int main() {
    try {
        Foo foo;
        throw 5;
    } catch(...) {
        std::cout << "Exception caught\n";
    }
}

使用std::uncaught_exceptions,我能够了解到有 * 一些 * 异常被抛出,但尚未被捕获。不幸的是,std::current_exception实际上并没有给予指向当前异常的指针,因为它只在catch子句中工作。(另见:Can I use std::current_exception during stack unwinding?)。因此,上面的实际输出是:

Number of uncaught exceptions: 1
Exception caught

没有线Stack unwinding due to exception
是否有其他方法可以实际获取指向当前抛出的异常的异常指针?(如果有多个,我希望得到最近的/内部的)。也许在新的C++标准中增加了一些东西?

wwodge7n

wwodge7n1#

没有办法做到这一点。更重要的是,你不应该“想”。
查询当前异常计数是一种机制,它允许您判断析构函数(或析构函数调用的代码)是否作为堆栈展开的一部分被调用。这样的代码应该是异常中立的。检查异常并根据异常的内容执行某些操作不是代码的工作。
根据抛出的异常执行不同操作的地方在catch块中。
还应该注意的是,即使current_exception确实返回了一个指向当前异常的指针,这实际上也不能满足您的需要。为什么?因为可能有 * 多个 * 异常展开堆栈。
假设一个析构函数被调用作为展开的结果。该析构函数代码可以在其堆栈上创建对象。这些堆栈对象的析构函数 * 不应该 * 认为自己由于解卷而被销毁(除非析构函数本身抛出了导致解卷的异常)。但是由于异常正在运行中,它们会错误地认为调用它们是因为解卷。
这就是为什么std::uncaught_exceptions返回一个整数,而不是布尔值。它返回飞行中的异常数,可以多于一个(就像上面的例子一样,作为展开的结果调用的析构函数本身可以抛出异常,只要它不让这些异常被发出)。在析构函数中,将其与当前std::uncaught_exceptions值进行比较。如果新值大于旧值,* 那么 * 你知道你的析构函数由于展开而被调用。

相关问题