GCC(libstdc++)运行时如何决定在异常处于活动状态时终止()
Posted
技术标签:
【中文标题】GCC(libstdc++)运行时如何决定在异常处于活动状态时终止()【英文标题】:How GCC (libstdc++) runtime decides to terminate() while an exception is active 【发布时间】:2019-10-08 06:57:02 【问题描述】:我们知道如果异常当前处于活动状态并且有另一个对 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
()。
【问题讨论】:
我说的是在 catch 块中投掷。它不必与最初抛出的异常对象相同。 @VTT 谢谢,这次我尝试了示例。 【参考方案1】:一旦出现catch
ed(当控制进入catch
部分时),异常就会停止“活动”。
【讨论】:
谢谢 +1,我现在可以回忆起论文“IA-64 的 C++ 异常处理”中的详细信息,您介意我在自己对问题的详细回答中解释这一点吗? @ultimatecause 当然,我不介意。毕竟这是你的问题。【参考方案2】:这个答案的功劳归于@HolyBlackCat,他在他的回答中暗示了这一点。
throw
的响应是一个复杂的过程,其中 C++ 运行时需要执行几个不同的操作。虽然实际过程可能由运行时的实现定义,但很少有东西可以共同理解。 This paper 可以提供更多信息。请参阅第 3.3 节。
在为throw
提供服务的过程中,将开始搜索适当的catch
。这本身可能会导致当前堆栈帧的展开。展开堆栈帧的副作用是调用当前帧中对象的相应析构函数。再次调用析构函数的这个动作将运行时降落在用户的代码区域(不安全)。完成后,我们再次进入运行时的区域(更安全)。
最后,当输入一个合适的catch
时,活动异常被销毁并开始执行处理程序的代码。由于这个原因,throw
如问题所示,不会遇到任何活动异常。
这也解释了为什么我们不应该 throw
一个超出范围的析构函数的异常。实际上,在析构函数中有一个 try....catch(...)
块以防止任何不良的 terminate
() 事件是一个好习惯。
【讨论】:
以上是关于GCC(libstdc++)运行时如何决定在异常处于活动状态时终止()的主要内容,如果未能解决你的问题,请参考以下文章
为啥异常不适用于 OSX 上的 gcc7 和 -static-libgcc?
Linux From Scratch(LFS11.0)编译交叉工具链 - GCC-11.2.0 中的 Libstdc++,第一遍