堆栈是否有c ++标准保证的异常展开?

fed*_*ino 19 c++ language-lawyer c++11

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

在完成异常对象([except.throw])的初始化之后,异常被认为是未捕获的,直到完成异常处理程序的激活([except.handle]).这包括堆栈展开.

标准杆15.5.3现行标准的.我试图理解最新的句子(This includes stack unwindings)是指什么:

  • 假设编译器必须负责展开堆栈吗?
  • 或者,它是说依赖于编译器是否放松堆栈?

问题来自以下片段:

#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();
}
Run Code Online (Sandbox Code Playgroud)

现在:

  1. 如果你按原样运行它(捕获异常),你会有一些堆栈展开的提示
  2. 如果你评论f();和取消注释g();(没有捕获异常),你有一堆堆栈没有被解开

所以,这两个实验似乎赞成上面的第一个子弹; clang ++和g ++都同意结果(但它不是判别式).

此外,在我看来,非常奇怪的是标准,在指定对象的实时时间持续时间时非常小心,这里留下了阴影.

愿有人澄清吗?堆栈是否为标准保证的未捕获异常展开?如果是的话,在哪里?如果没有,为什么?

Nic*_*las 31

堆栈是否为标准保证的未捕获异常展开?

保证堆栈展开仅针对捕获的异常([except.handle]/9):

如果找不到匹配的处理程序,std::terminate()则调用该函数; 在此调用之前是否展开堆栈std::terminate()是实现定义的.

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

如果没有,为什么?

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

如果你没有这样做......那你就不在乎.

如果您真的需要堆栈始终展开,那么您可以将main代码(和任何线程函数)放在一个try {} catch(...) {throw;}块中.