函数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()函数?什么时候叫destructor ?我找不到逻辑:((((((((
谁能告诉我何时调用terminate(),何时调用unexpected()?
在您的示例中,将调用终止处理程序。您可以在这里验证。
关于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表达式试图重新抛出异常而没有异常时已处理(15.1),或
-当
std::unexpected
抛出先前违反的dynamicexception-不允许的异常时而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)。-end note]
2在这种情况下,调用
std::terminate()
(18.8.3)。[…]
关于std::unexpected()
,根据第15.4/9段:
每当抛出异常并且搜索处理程序(15.3)遇到a的最外层块时函数的异常规范不允许出现异常,则
-如果异常规范是动态异常规范,则函数
std::unexpected()
是动态异常规范叫(15.5.2)—否则,调用函数std::terminate()(15.5.1)。
相关规则在标准中有明确的定义,有许多规则,但简单地说,适用于您的示例的规则是:
-
throw
没有catch
将导致调用terminate
或为其设置的函数。 - 当抛出的异常与异常规范不匹配时,将导致调用
unexpected
或为其设置的函数。
15.1抛出异常
对位8:
如果当前没有处理异常,则执行不调用操作数的throw表达式终止()(15.5.1)。
15.4异常规范
对位8:
每当抛出异常并且搜索处理程序(15.3)遇到a的最外层块时函数带有异常说明,则调用函数unexpected() (15.5.2)不允许出现
异常
为什么你的程序调用
abort
你的程序有未定义的行为。它符合您适当设置terminate_handler
的事实,并且正如您注意到的那样,程序确实导致对f()
的调用,但terminate_handler
函数所需的行为是:
terminate_handler应该终止程序的执行而不返回给来电者。
你的terminate_handler
函数f
不满足这个条件,因此导致未定义的行为,从技术上讲,你可以得到任何行为,你的实现选择在这种情况下调用abort
。没有什么可以阻止它这样做。