GCC (libstdc++) 运行时如何在异常处于活动状态时决定终止 ()

How GCC (libstdc++) runtime decides to terminate() while an exception is active

本文关键字:活动状态 决定 终止 运行时 libstdc++ GCC 异常      更新时间:2023-10-16

我们知道,如果异常当前处于活动状态并且有另一个调用throw,则会调用terminate((。

想知道是什么原因导致这种情况与catch块从内部throw的情况区分开来吗?我假设如果一个catch块正在执行,它表示一个活动的异常。

class exception_type{}
try{ ... throw obj; ... 
}catch(exception_type& obj){
...
... 
throw x;
...
}

从这个代码示例中,因为我们在catch块中还有另一个throw,它应该被动态封闭try块中的另一个处理程序捕获。 所以这似乎是catch内部throw的有效使用。但此时我们已经有一个异常处于活动状态。为什么它不应该导致调用terminate((?或者换句话说,gcc 的 c++ 运行时如何准确地识别已经存在一个异常处于活动状态并且需要调用terminate((。

异常在catched(当控件进入catch部分时(立即停止"活动"。

这个答案的功劳要归功于@HolyBlackCat,他在回答中暗示了这一点。

throw的响应是一个复杂的过程,其中C++运行时需要执行多个不同的操作。虽然实际过程可以通过运行时的实现来定义,但很少有共同点可以理解。这篇论文可以提供更多的启示。请参阅第 3.3 节。

在为throw提供服务的过程中,开始搜索适当的catch。这本身可能会导致当前堆栈帧的展开。展开堆栈帧的副作用是调用当前帧中对象的相应析构函数。再次调用析构函数的此操作将运行时置于用户的代码区域(不安全(。完成此操作后,我们再次进入运行时的区域(更安全(。

最后,当输入合适的catch时,活动异常将被销毁并开始执行处理程序的代码。因此,所讨论的throw不会遇到任何活动异常。

这也解释了为什么我们不应该从超出范围的析构函数中throw异常。实际上,在析构函数中有一个try{....}catch(...)块以防止任何不幸的terminate((事件,这将是一个很好的做法。