关于堆栈展开,C++标准说:
在完成异常对象的初始化 ([except.throw]) 直到完成异常处理程序的激活([except.handle])期间,异常被视为未处理。这包括堆栈展开。
参见当前标准的第15.5.3节。我试图理解最后一句话 (This includes stack unwinding.
) 所指的是什么:
- 它意味着编译器必须负责展开堆栈吗?
- 还是说展开堆栈是否进行取决于编译器?
这个问题源于以下代码片段:
#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();
}
现在:
- 如果按照原样运行它(捕获异常),则会给出堆栈展开的提示。
- 如果将
f();
注释掉并取消注释g();
(不捕获异常),则可以得到堆栈未被展开的提示。
因此,这两个实验似乎支持上面的第一个要点;clang++和g++都对结果达成了一致意见(但这并不是一个判别标准)。
另外,我觉得很奇怪的是,标准非常小心地指定了对象的“存活时间”和“持续时间”,却在这里留下了一个阴影。
是否有人可以澄清?未捕获异常的堆栈展开是否得到了标准的保证?如果是,那在哪里?如果不是,为什么?
s
并没有被销毁。它会在f()
返回后被销毁。 - aschepler