当结束函数f()和g()时会发生什么?
#include<iostream>
using namespace std;
class A
{
~A(){}
}
void f()
{
cout << "terminate" << endl;
}
void g()
{
cout << "unexpected" << endl;
}
int main()
{
set_terminate(f);
set_unexpected(g);
throw 5;
cout << "end" << endl;
return 0;
}
为什么叫abort()函数? 什么时候被称为destruktor?我找不到逻辑:((((((
答案 0 :(得分:3)
任何人都可以告诉我何时调用terminate(),以及何时意外()?
在您的情况下,将调用您的终止处理程序。您可以验证here。
关于std::terminate()
,第15.5.1 / 1-2段包含一个注释,该注释列出了调用它的情况的详尽列表(粗体字的部分适用于您的情况强>):
1在某些情况下,必须放弃异常处理,以获得不那么微妙的错误处理技术。 [ 注意: 这些情况是:
- 当异常处理机制完成异常对象的初始化之后 但在激活异常处理程序(15.1)之前,调用通过异常退出的函数, 或
- 当异常处理机制无法找到抛出异常的处理程序(15.3)或
- 当搜索处理程序(15.3)遇到具有noexcept规范的函数的最外面的块时 不允许例外(15.4)或
- 在堆栈展开期间(15.2)通过抛出异常终止对象的销毁时, 或
- 当通过静态或线程存储持续时间(3.6.2)的非局部变量的初始化退出时 例外,或
- 当通过异常(3.6.3)或
退出具有静态或线程存储持续时间的对象时- 执行通过
std::atexit
或std::at_quick_exit
注册的功能时,异常退出 (18.5),或- 当没有操作数的throw-expression尝试重新抛出异常并且没有异常时 处理(15.1)或
- 当
std::unexpected
抛出先前违反的动态异常所不允许的异常时 - 规范和std :: bad_exception不包含在该动态异常规范中 (15.5.2),或- 调用实现的默认意外异常处理程序(D.11.1)或
时- 为已捕获的对象调用函数
std::nested_exception::rethrow_nested
时 没有例外(18.8.6),或- 执行线程的初始函数时,通过异常(30.3.1.2)或
退出- 在std :: thread类型的对象上调用析构函数或复制赋值运算符时 引用可连接线程(30.3.1.3,30.3.1.4)。 - 后注]
2在这种情况下,调用
std::terminate()
(18.8.3)。 [...]
关于std::unexpected()
,根据第15.4 / 9段:
每当抛出异常并且搜索处理程序(15.3)遇到a的最外面的块时 函数具有不允许异常的异常规范,然后,
- 如果异常规范是动态异常规范,则函数
std::unexpected()
是 叫(15.5.2),- 否则,调用函数std :: terminate()(15.5.1)。
答案 1 :(得分:1)
相关规则在标准中有明确规定,有许多规则但只是说并适用于你的例子:
throw
的catch
会调用terminate
或为其设置的函数。 unexpected
或为其设置的函数。 15.1抛出异常
第8段:
如果当前没有处理异常,则执行不带操作数调用的throw-expression terminate()(15.5.1)。
15.4例外规范
第8段:
每当抛出异常并且搜索处理程序(15.3)遇到a的最外面的块时 具有异常规范的函数,如果例外规范,则调用函数unexpected()(15.5.2) 不允许例外
为什么您的程序会调用
abort
?
您的程序有一个未定义的行为。它符合以下事实:您正确设置terminate_handler
,并且您注意到程序确实会调用f()
,但terminate_handler
函数所需的行为是:
C ++ 03标准18.6.3.1.2:
terminate_handler应终止程序的执行而不返回 给来电者。
您的terminate_handler
函数f
不满足此条件,因此导致未定义的行为,从技术上讲,您可能会获得任何行为,您的实现选择在此调用abort
情况。没有什么能阻止它这样做。