保证在突然终止或退出时在C ++中调用函数

时间:2011-08-01 16:35:20

标签: c++ exception-handling

在突然终止或退出期间,可以保证在C ++中调用哪些函数来执行清理活动。

8 个答案:

答案 0 :(得分:8)

根据“突然终止”的含义,有几种不同的选择:

  • 全局析构函数将在正常终止时被调用(从main返回,或致电exit())。
  • atexit()注册一个在正常终止时调用的函数。
  • std::set_terminate注册一个函数,该函数将在抛出异常但未被捕获时被调用,或者“由于其他原因必须终止异常处理”。
  • sigaction()注册当程序收到信号时要调用的函数,其中许多函数通常会突然终止程序。当程序处于内部不一致状态时,可以调用信号处理程序,因此它们可以做的事情非常受限。例如,他们不能做任何可能分配内存的事情。此外,此API在Windows上不可用;有等价物,但我不熟悉它们。

请注意,所有常用的操作系统都至少提供了一种突然终止程序的方法,无法从代码中截获 。例如,Unix有信号9(SIGKILL),您无法为其注册处理程序。 这是一个功能,而不是一个错误。你,用户,需要一种方法来使一个过程消失,即使它已经尽其所能使其自身坚不可摧。此外,当用户的宠物兔子通过计算机上的电源线啃咬时,没有代码可以保护您的过程。因此,您可以更好地利用时间来设计程序,以便从崩溃中恢复,而不是在崩溃发生时尝试清理。有关详情,请参阅有关“crash-only design”的文章。

答案 1 :(得分:2)

了解atexit here。但是,它不会在所有情况下调用(例如,调用abort不会触发您使用atexit注册的函数。)

你可以实现自己的信号处理程序,然后所有信号都会传递给你,你可以为它们做任何事情。

答案 2 :(得分:1)

您正在寻找set_terminate()

http://www.cplusplus.com/reference/std/exception/set_terminate/

在同一个标​​题中还有其他类似的功能,可用于补充方案。

答案 3 :(得分:1)

int main()
{
    try
    {
        // all your code here
    }
    catch(...)
    {
        // cleanup
    }
    return 0;
}

答案 4 :(得分:0)

你在做什么环境?突然之间你的意思是Ctrl + C还是杀死-9信号? 在unix / linux上你可以屏蔽一些信号并提供处理程序,但据我所知,你无法屏蔽所有信号(9是一个无法屏蔽的信号示例,它会突然终止你的进程)

可以使用一些甚至更低级别的操作系统操作覆盖,但我不熟悉。

答案 5 :(得分:0)

我不是专家,我只知道一些关于C ++的东西,但我知道你可以在Unix和C中创建句柄以检测具体信号然后执行一个函数然后通过“例如,退出(n)。

您可以使用signalsigaction执行此操作,但问题是您只能将此方法用于除SIGKILL或SIGSTOP之外的任何信号。

答案 6 :(得分:0)

没有任何功能可以捕获所有场景并适用于所有平台。如果你需要Windows的东西,你也必须处理SEH(结构化异常处理)。您必须为执行常见清理代码的各种方案(SEH,C ++异常,SIGABRT,终止等)定义和设置处理程序。检查zack在这里处理SIGABRT信号的响应。

对于SEH,您可以添加SE转换器来处理SE激励并将它们转换为C ++异常,请查看_set_se_translator以获取有关如何处理SEH异常的更多信息。

您可以参考this documentation for set_terminate handlerthis is a good reference for set_unexpected

您必须编写自己的处理程序,并为每个方案调用。

最后,为了这个目的,我建议使用一些现有的库,我喜欢crashrprt

答案 7 :(得分:0)

您熟悉信号处理吗?我建议你先学习,然后回答有关它的问题。看起来有几个人已经提到了它,但这里有一个很好的资源来检查:

http://www.gnu.org/s/hello/manual/libc/Signal-Handling.html

编写自己的信号处理程序将允许您确定捕获特定信号时要执行的操作。如上所述,有一些不能被覆盖,并且有充分的理由。你不想让某人覆盖kill -9只是因为可以创建一个不可能杀死的程序。但是,可以按照您选择的方式捕获和处理直接终止信号或ctrl-c,ctrl-d等等。