如何在 C++ 中优雅地终止进程?

问题描述 投票:0回答:2

“优雅地”我的意思是:“在终止之前调用本地/静态对象 dtor,而不生成 coredump”。

我尝试过:

  • std::exit()
    (以 coredump 终止)
  • std::_Exit()
  • std::abort()
    (以 coredump 终止)
  • std::raise(SIGKILL)
  • std::terminate()
    (以 coredump 终止)

它们都立即终止进程,而不调用本地/静态对象 dtor。我的问题是:在我的代码库中,我有一些无法容忍的错误,应该终止该进程;但是,我也有一些全局/本地对象(例如记录器)需要在终止之前调用 dtor。


  • 编译器:Clang 12
  • 操作系统:Linux 5.10.0-1
  • 拱门:Aarch64
c++ linux
2个回答
12
投票

如果您希望正确销毁局部变量,那么您唯一的解决方案是

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
一样,但不正常)。如果没有,信号可能会被捕获或最终导致进程立即被终止。

它们都不会执行堆栈展开来销毁具有自动存储持续时间的局部变量。


1
投票

调用

exit()
函数,并将正确的错误代码作为参数传递。指定 0 表示正常终止,指定任何大于 0 的值表示错误。一个常见的错误是传递一个负值,该负值会被
systemd
等收割者程序误解,这些程序会认为进程因收到信号而终止。
此外,为了进行额外的清理,您可以通过
atexit()
注册回调函数,以便在退出时调用。

© www.soinside.com 2019 - 2024. All rights reserved.