“优雅地”我的意思是:“在终止之前调用本地/静态对象 dtor,而不生成 coredump”。
我尝试过:
std::exit()
(以 coredump 终止)std::_Exit()
std::abort()
(以 coredump 终止)std::raise(SIGKILL)
std::terminate()
(以 coredump 终止)它们都立即终止进程,而不调用本地/静态对象 dtor。我的问题是:在我的代码库中,我有一些无法容忍的错误,应该终止该进程;但是,我也有一些全局/本地对象(例如记录器)需要在终止之前调用 dtor。
如果您希望正确销毁局部变量,那么您唯一的解决方案是
return
返回调用堆栈,直至并包括 main
,或者抛出在 main
中捕获的异常,然后从它。
但是,您在问题中针对不同库调用所述的行为不正确,特别是
std::exit()
正常退出。不应生成核心转储,虽然它不会破坏具有自动存储持续时间的变量,但它会调用静态存储持续时间对象的析构函数。
std::_Exit
也正常退出,但与std::exit
相反,不执行任何清理(不是静态存储持续时间对象或std::at_exit
/std::at_quick_exit
处理程序)。
另外三个调用导致程序异常终止,这似乎不是你想要的。
std::raise(SIGKILL)
本质上不执行任何类型的清理。它只会引发 SIGKILL。确切的行为取决于操作系统。至少对于 Linux 来说,它会立即导致内核终止进程,而无法重新获得控制权。
std::terminate()
将调用(可能是用户提供的)终止处理程序。默认终止处理程序调用 std::abort
。
std::abort
导致 SIGABRT 信号在没有任何清理的情况下被引发(就像 std::_Exit
一样,但不正常)。如果没有,信号可能会被捕获或最终导致进程立即被终止。
它们都不会执行堆栈展开来销毁具有自动存储持续时间的局部变量。
调用
exit()
函数,并将正确的错误代码作为参数传递。指定 0 表示正常终止,指定任何大于 0 的值表示错误。一个常见的错误是传递一个负值,该负值会被 systemd
等收割者程序误解,这些程序会认为进程因收到信号而终止。atexit()
注册回调函数,以便在退出时调用。