我一直在玩C++中的异常处理和析构函数异常以更好地理解它,并且我遇到了一些我无法解释的奇怪行为(我希望有人在这里可以帮我)。在MSVC中析构函数抛出异常
我已经写了这个简单的代码。 这是一个异常类(Foo),在被破坏时抛出。 这里的意图是从抛出到main()的任何地方传播异常,我明确地捕获它并阻止它重新抛出它自己。
#include <iostream>
class Foo
{
public:
Foo();
virtual ~Foo();
void stopThrowing() { keepThrowing_ = false; }
private:
bool keepThrowing_;
};
Foo::Foo(): keepThrowing_(true)
{
std::cout << "Foo created: " << this << std::endl;
}
Foo::~Foo()
{
std::cout << "Foo destroyed: " << this << std::endl;
if (keepThrowing_)
{
throw Foo();
}
}
int main()
{
try {
try {
throw Foo();
} catch (const Foo&) {
std::cout << "Foo caught" << std::endl;
}
} catch (Foo& ex) {
std::cout << "Foo caught 2" << std::endl;
ex.stopThrowing();
} catch (...) {
std::cout << "Unknown exception caught 2" << std::endl;
}
std::cout << "Done" << std::endl;
return 0;
}
我知道,这绝不应该用C++来完成,但是这并不是问题的关键 - 我想要了解什么是MSVC x86和x64异常处理之间的不同(我将在解释下一段)。
当我编译使用MSVC的x86代码(我用2010为主,但我也查了这个在2005年和2012年),一切都很好,它按预期工作:
Foo created: 001AFC1C
Foo caught
Foo destroyed: 001AFC1C
Foo created: 001AF31C
Foo caught 2
Foo destroyed: 001AF31C
Done
当我编译此代码为使用MSVC 64,它失败严重:
Foo created: 000000000047F9B8
Foo caught
Foo destroyed: 000000000047F9B8
Foo created: 000000000047D310
Foo destroyed: 000000000047D310
Foo created: 000000000047C150
Foo destroyed: 000000000047C150
Foo created: 000000000047AF90
Foo destroyed: 000000000047AF90
Foo created: 0000000000479DD0
...
在这一点,它使创建和销毁的Foo对象,直到它到达一个堆栈溢出,并崩溃。
如果我改变析构函数这个片段(抛出一个int,而不是美孚):
Foo::~Foo()
{
std::cout << "Foo destroyed: " << this << std::endl;
if (keepThrowing_)
{
throw 1;
}
}
我收到以下输出:
Foo created: 00000000008EF858
Foo caught
Foo destroyed: 00000000008EF858
然后程序到达一个调试断言( std :: terminate()被调用)时,执行throw 1;
。
我的问题是:这里发生了什么? 它看起来像x64上的MSVC不赞成这种行为,但它只是感觉不对,因为它在x86上工作。我使用MinGW和MinGW-w64对x86和x64编译了这些代码,并且这两个程序都按预期工作。这是MSVC中的错误吗? 任何人都可以想出一种方法来绕过这个问题,或者为什么微软决定阻止这种情况发生在x64上?
谢谢。