我编写了以下程序:
// Example program
#include <iostream>
#include <string>
#include <exception>
struct A {
A() {
std::cout << "A ctor" << std::endl;
}
~A() {
std::cout << "A dtor" << std::endl;
try {
throw std::exception();
} catch (std::exception &e) {
std::cout << "Internal exception caught" << std::endl;
}
}
};
int main()
{
try {
A a;
throw std::exception();
} catch (std::exception &e) {
std::cout << "External exception caught" << std::endl;
}
}
我期望的输出是:
A ctor
A dtor
Internal exception caught
External exception caught
这就是我在GCC中获得的东西。但是,当我使用Visual Studio(2013版)时,得到的输出是:
A ctor
External exception caught
这里发生了什么?
MSVC2013在这里是错误的,GCC是正确的。不幸的是,我现在无法从标准中找到合适的引用,但是根据std :: uncaught_exception:
例如,如果堆栈展开导致堆栈分配的对象被破坏,则该对象的析构函数可以运行引发异常的代码,只要该异常在转义析构函数之前被某些catch块捕获即可。
有关更多详细信息,请参见此处的“堆栈展开时的抛出”部分。
最后,正如@StoryTeller所提到的,此行为在较新的MSVC版本中无法重现。
我可以找到的标准中最接近的匹配项是下一个(来自N3936草案):
15.1引发异常[except.throw]
- 如果异常处理机制在完成异常对象的初始化之后但在激活异常处理程序之前调用了通过异常退出的函数,则将调用std :: terminate。
因此,从形式上讲,在可能处理异常的堆栈展开过程(包括析构函数)中调用函数是完全有效的,但是如果该函数内部的异常未被适当的catch
块捕获,则std::terminate
必须调用该函数。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句