在C++中,我如何在析构函数的主体中检测堆栈是否由于抛出异常而被解缠?一旦检测到,我能否获取活动异常的引用?
我之所以问这个问题,是因为我想添加一些调试代码,以解释为什么可能会出现某种情况以及是否是由于异常引起的。
在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.
}
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()
跟踪代码调用时未捕获异常的数量。更多信息可以在cppreference页面上找到。有一个 std::uncaught_exception()
函数。然而,你能做的唯一有用的事情是重新抛出它并尝试捕获它以获取异常对象的访问权限。通常情况下,你不应该从任何析构函数中抛出异常。
try{ throw; } catch(std::exception const& e){ /*handle it*/}
- Xeo