什么是C ++终止处理程序Right Thing(TM)?

时间:2009-06-29 14:58:13

标签: c++ exception-handling resources standards terminate

C ++标准提供std::set_terminate函数,它允许您指定实际调用的函数std::terminate。只有在严峻的情况下才能调用std::terminate,并且确定标准在被调用时所描述的情况是可怕的(例如未捕获的异常)。当std::terminate被调用时,情况似乎与失去记忆相似 - 你可以理智地做的事情并不多。

我已经读过它可以用来确保资源被释放 - 但是对于大多数资源,这应该在进程退出时由OS自动处理(例如文件句柄)。从理论上讲,我可以看到一个案例,如果说,你需要在退出时由于崩溃而向服务器发送特定的消息。但是OS处理的大部分时间应该足够了。

何时使用终止处理程序Right Thing(TM)?

更新:People interested in what can be done with custom terminate handlers might find this non-portable trick useful.

3 个答案:

答案 0 :(得分:7)

这只是乐观的:

  

但是对于大多数资源,当进程退出时,操作系统应自动处理

关于操作系统自动处理的唯一资源是“文件句柄”和“内存”(这可能因操作系统而异)。 实际上所有其他资源(如果有人拥有由OS的I自动处理的资源列表 我很乐意)需要由操作系统手动发布。

最好的办法是避免使用terminate()退出并尝试通过强制堆栈正确展开来控制关闭。 这将确保正确调用所有析构函数并释放资源(通过析构函数)。

关于我唯一要做的就是记录问题。因此,当它确实发生时,我可以返回并修复代码,以便它不会再发生。我喜欢我的代码来很好地解除堆栈的资源释放,但这是一种观点,有些人喜欢在事情变得严重时突然停止。

我的终止列表名称为:

通常,当异常处理机制找不到抛出异常的处理程序时,会调用它。一些具体的例子是:

  • 异常转义main()
    • 注意:实现定义了堆栈是否在此处展开​​。 因此,我总是捕获主要然后重新抛出(如果我没有明确处理)。 这样我就可以保证堆栈的展开(跨所有平台)并且仍然可以获得操作系统异常处理机制的好处。
  • 同时传播的两个例外。
    • 当另一个异常传播时,异常会转义desatructor。
    • 抛出的表达式会生成异常
  • 主要之前或之后的例外。
    • 如果异常转义全局对象的构造函数/析构函数。
    • 如果异常转义函数静态变量的析构函数。 (即小心非局部静态对象的构造函数/析构函数)
    • 异常转义用atexit()注册的函数。
  • 当没有异常正在传播时重新抛出。
  • 未列出的异常会转义具有异常说明符列表的方法/函数。
    • via unexpected。

答案 1 :(得分:0)

Martin York的 answer中的声明类似,我在自定义终止处理程序中所做的唯一事情是记录问题,以便我可以识别并纠正有问题的代码。这是我发现使用自定义终止处理程序的唯一实例是 Right Thing


由于它是实现定义的,无论堆栈是否在调用std::terminate()之前展开,我有时add code to generate a backtrace才能找到未捕获的异常 1

1)在Linux平台上使用GCC时,这似乎对我有用。

答案 2 :(得分:-1)

我认为正确的问题是如何避免调用终止处理程序,而不是何时使用它。