【问题标题】:How GCC (libstdc++) runtime decides to terminate() while an exception is activeGCC(libstdc++)运行时如何决定在异常处于活动状态时终止()
【发布时间】: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 谢谢,这次我尝试了示例。

标签: c++ exception gcc g++


【解决方案1】:

一旦出现catched(当控制进入catch 部分时),异常就会停止“活动”。

【讨论】:

  • 谢谢 +1,我现在可以回忆起论文“IA-64 的 C++ 异常处理”中的详细信息,您介意我在自己对问题的详细回答中解释这一点吗?
  • @ultimatecause 当然,我不介意。毕竟这是你的问题。
【解决方案2】:

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

throw 的响应是一个复杂的过程,其中 C++ 运行时需要执行几个不同的操作。虽然实际过程可能由运行时的实现定义,但很少有东西可以共同理解。 This paper 可以提供更多信息。请参阅第 3.3 节。

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

最后,当输入一个合适的catch 时,活动异常被销毁并开始执行处理程序的代码。由于这个原因,throw 如问题所示,不会遇到任何活动异常。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多