以下代码通过提供错误退出
“abort()被称为”。
是由于析构函数抛出异常吗?我知道从析构函数中抛出异常会导致未定义的行为,但也存在反向参数。而且同样的程序在VS 2012中也能正常工作。
#include "stdafx.h"
#include<iostream>
using namespace std;
class Txn
{
public:
Txn()
{
cout<< "in Constructor" << endl;
};
~Txn()
{
try
{
cout << "in destructor" << endl;
throw 10;
}
catch(int i)
{
cout << "in destructor exception" << endl;
throw;
}
}
};
int main()
{
try
{
Txn t;
}
catch (int i)
{
cout << "Exception" << i << endl;
}
return 0;
}
VS2017发行说明未提及有关异常处理更改的任何内容。
所以我有以下问题:
请建议。
答案 0 :(得分:7)
这里的问题是默认情况下所有析构函数都是noexcept(true)
。在不更改的情况下抛出异常将立即调用std::terminate
。如果我们使用
class Txn
{
public:
Txn()
{
cout<< "in Constructor" << endl;
};
~Txn() noexcept(false)
{
try
{
cout << "in destructor" << endl;
throw 10;
}
catch(int i)
{
cout << "in destructor exception" << endl;
throw;
}
}
};
int main()
{
try
{
Txn t;
}
catch (int i)
{
cout << "Exception" << i << endl;
}
return 0;
}
程序按预期运行。
这在VS2012中起作用但不是VS2017的原因是在C ++ 11之前,析构函数可以抛出而不需要指定它。使用C ++ 11 noexcept
说明符以及默认情况下所有析构函数都为noexcept
的更改会导致它在VS2017中断。
答案 1 :(得分:4)
默认情况下,析构函数不会抛出异常(noexcept
)。您可以通过添加noexcept(false)
来告诉编译器这个析构函数没有使用默认值。
在这个例子中尝试时,我们现在从编译器得到一个不同的诊断 - 析构函数永远不会到达终点。析构函数永远不会完全破坏对象是不好的......
要“修复”这个,我必须使用if
条件进行重新抛出。
class Txn
{
public:
Txn()
{
cout<< "in Constructor" << endl;
};
~Txn() noexcept(false)
{
try
{
cout << "in destructor" << endl;
throw 10;
}
catch(int i)
{
cout << "in destructor exception" << endl;
if (i == 10) throw;
}
}
};
答案 2 :(得分:-1)
未定义的行为可以是任何,包括对abort()的调用;只要避免可能诱发它的一切。
不禁止从析构函数中抛出,但在try / catch中执行此操作可能会导致抛出双重异常。