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