我试图理解为什么析构函数抛出异常是一个非常糟糕的主意。通过谷歌搜索,我理解如果析构函数抛出,比如说,在块范围对象的销毁过程中,对象的销毁就会停止,如果还有其他对象,那么我们就会发生内存泄漏。
但是就其本身而言,抛出异常的析构函数是如此糟糕?例如(完整示例):
struct A
{
int a;
char b;
A() : a(10), b('a') { }
~A(){ throw std::exception(); }
};
int main()
{
A a; //destructor throws, but there're no more objects to destruction
//therefore I think there's no memory leak
}
我们在上面的程序中获得了UB吗?
答案 0 :(得分:5)
在这个简单的例子中,抛出了bar()中的异常并且展开了堆栈,破坏了a,这会引发另一个异常。在这种情况下可以抛出哪个异常?
struct A
{
int a;
char b;
A() : a(10), b('a') { }
~A(){ throw std::exception(); }
};
void bar ()
{
A a;
throw std::exception();
}
int main()
{
bar();
}
来自C++ FAQ
在堆栈展开期间,所有堆栈中的所有本地对象 帧被破坏。如果其中一个析构函数抛出异常 (假设它抛出了一个Bar对象),C ++运行时系统处于一种不可取的状态 情况:它应该忽略Bar并最终进入} catch(Foo e) {它最初在哪里?它应该忽略Foo并且看起来 for a catch(Bar e){handler?也没有好的答案 选择失去了信息。
所以C ++语言保证它会调用terminate() point和terminate()终止进程。