c++ - c++ 标准是否保证堆栈展开并出现异常?

标签 c++ c++11 language-lawyer

关于堆栈展开,c++ 标准说:

An exception is considered uncaught after completing the initialization of the exception object ([except.throw]) until completing the activation of a handler for the exception ([except.handle]). This includes stack unwinding.

par 15.5.3的现行标准。我试图理解最新的句子(这包括堆栈展开)指的是:

  • 是否假定编译器必须负责展开堆栈?
  • 或者,是否展开堆栈取决于编译器?

问题来自以下片段:

#include <iostream>
#include <exception>

struct S{
    S() { std::cout << " S constructor" << std::endl; }
    virtual ~S() { std::cout << " S destructor" << std::endl; }
};

void f() {
    try{throw(0);}
    catch(...){}
}

void g() {
    throw(10);
}

int main() {
    S s;
    f();
    //g();
}

现在:

  1. 如果您按原样运行它(捕获异常),您会看到堆栈展开的提示
  2. 如果您注释 f(); 并取消注释 g();(未捕获异常),则提示堆栈未展开

所以,这两个实验似乎支持上面的第一个项目符号; clang++ 和 g++ 都同意结果(但它不是判别式)。

另外,在我看来很奇怪的是,在指定对象 live timeduration 时非常小心的标准在这里留下了阴影。

谁能解释一下?标准是否保证未捕获异常的堆栈展开?如果是,在哪里?如果不是,为什么?

最佳答案

Is stack unwinding for uncaught exceptions guaranteed by the standard?

保证堆栈展开只发生在捕获异常([except.handle]/9):

If no matching handler is found, the function std::terminate() is called; whether or not the stack is unwound before this call to std::terminate() is implementation-defined.

所以它是实现定义的,否则。

If not, why?

如果发生未捕获的异常,标准会调用 std::terminate。这代表程序执行的结束。如果您有某种特定于平台的方式来记录有关当时系统状态的信息,您可能不希望该状态受到堆栈展开的干扰。

如果你不这样做......那么你不管用哪种方式。

如果您确实需要始终展开堆栈,那么您可以将您的 main 代码(以及任何线程函数)放在 try {} catch(...) {throw ;} block 。

关于c++ - c++ 标准是否保证堆栈展开并出现异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39962999/

相关文章:

c++ - std::shared_ptr 指向的对象何时被删除?

c++ - shared_ptr 从 unique_ptr 到数组

c++ - C++中的虚拟继承和统一初始化

c++ - 封装在头文件中

c++ find()用于成员函数的映射

c++ - 我怎样才能通过引用弹出一些东西?

c++ - 友元函数的参数依赖查找

c++ - 将 UILabel 的内容转换为图像并将其保存到磁盘

c++ - 表达式的求值会在什么情况下发生

java - (编译器) else if(true) vs else 场景