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

Function guaranteed to be called in C++ during abrupt termination or exit

本文关键字:退出 调用 函数 终止 c++ 突然      更新时间:2023-10-16

c++中什么函数保证在突然终止或退出时被调用,可以执行清理活动?

根据您对"突然终止"的定义,有几个不同的选项:

  • 全局析构函数将在正常终止(从main返回,或调用exit())时被调用。
  • atexit()注册一个在正常终止时调用的函数。
  • std::set_terminate注册一个函数,该函数将在抛出异常但未捕获时调用,或者当"异常处理因其他原因必须终止"时调用。
  • sigaction()注册了程序接收到信号时调用的函数,其中许多函数通常会突然终止程序。信号处理程序可能在程序处于内部不一致状态时被调用,因此它们所能做的事情非常有限。例如,它们不能做任何可能分配内存的事情。此外,此API在Windows上不可用;有类似的,但我不熟悉。
请注意,所有常用的操作系统都提供了至少一种突然终止程序的方法,使不能从代码中截取。例如,Unix有信号9 (SIGKILL),您不能为其注册处理程序。这是一个特性,而不是一个bug。你,用户,需要一种方法让进程消失,即使它已经尽了一切力量使自己坚不可摧。此外,当用户的宠物兔子咬断计算机上的电源线时,没有代码可以保护您的进程。正因为如此,更好地利用您的时间来设计您的程序,以便从崩溃中干净地恢复,而不是在崩溃发生时试图清理。有关这方面的更多信息,请参阅"仅限崩溃设计"这篇文章。

点击这里阅读atexit。然而,它不会在所有情况下被调用(例如,调用abort将不会触发您在atexit中注册的函数)。

你可以实现你自己的信号处理程序,然后所有的信号将传递到那里,你可以为每个信号做任何事情。

您要找的是set_terminate()

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

在相同的头文件中还有其他类似的函数,可用于补充场景。

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

你在什么环境下工作?突然你的意思是Ctrl+C或杀死-9信号?在unix/linux上,您可以屏蔽一些信号并提供处理程序,但据我所知,您不能屏蔽所有信号(9是一个不能屏蔽的信号的例子,它会突然杀死您的进程)

对OS操作的一些甚至更低级别的重写是可用的,但我不熟悉。

我不是专家,我只知道一些关于c++的事情,但我知道你可以在Unix和C中创建句柄,以便检测一个具体的信号,然后,执行一个函数,然后,通过"exit(n)"终止程序。

您可以使用signal或sigaction来实现它,但问题是您只能对除SIGKILL或SIGSTOP之外的任何信号使用此方法。

你熟悉信号处理吗?我建议你们先研究一下,然后带着相关的问题回来。似乎已经有几个人提到过它,但这里有一个很好的资源来检查:

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

编写自己的信号处理程序将允许您确定在捕获特定信号时要做什么。如前所述,有一些不能被重写,并且有很好的理由。您不希望仅仅因为创建了一个不可能被杀死的程序而让某人重写kill -9。然而,一个直接的终止信号或诸如ctrl-c, ctrl-d等,可以被捕获并以您选择的方式处理。

没有一个函数可以捕获所有场景并在所有平台上工作。如果你需要一些Windows的东西,你也必须处理SEH(结构化异常处理)。您必须为各种场景(SEH、c++ Exceptions、SIGABRT、Terminate等)定义和设置处理程序,以执行常见的清理代码和。查看zack的响应在这里处理SIGABRT信号

对于SEH,您可以添加一个SE转换器来处理SE异常并将其转换为c++异常,有关如何处理SEH异常的更多信息,请参阅_set_se_translator。

你可以参考这个文档来了解set_terminate处理程序,这是set_unexpected处理程序的一个很好的参考。

你必须编写自己的处理程序,它将在每种情况下被调用。

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

相关文章: