std::quick_exit 和 std::abort 有什么区别,为什么需要 std::quick_exit

What is the difference between std::quick_exit and std::abort and why was std::quick_exit needed?

本文关键字:std exit quick 为什么 abort 什么 区别      更新时间:2023-10-16

C++11 引入了一种完成程序执行的新方法 — std::quick_exit

引用N3242 18.5(第461页(:

[[noreturn]] void quick_exit(int status) noexcept;

效果:调用at_quick_exit注册的函数被调用 以与它们的注册相反的顺序,除了一个函数 应在任何先前注册的函数之后调用 在注册时已经调用。对象不得 因召唤quick_exit而被摧毁。如果控件离开 注册函数由quick_exit调用,因为该函数没有 为引发的异常提供处理程序,terminate()应调用。 [ 注意:at_quick_exit可以从不同的函数调用已注册的函数 线程比注册它的线程,所以注册的函数应该 不依赖于具有线程存储持续时间的对象标识。— 尾注] 调用注册函数后,quick_exit应调用 _Exit(status) .[ 注意:不会刷新标准文件缓冲区。参见:ISO C 7.20.4.4。— 尾注 ]

由于std::abort(void)std::_Exit(int status)的定义仅在将状态传递给父进程的能力上有所不同,因此提出了我的问题。

这是否意味着std::quick_exitstd::abort之间的唯一语义区别是std::quick_exit调用使用std::at_quick_exit注册的函数并允许设置返回的状态?

引入此功能的理由是什么?

这里有

一篇很好的文章,我只是总结一下。 添加此功能是为了专门处理使用线程时干净地结束程序的困难。 从本质上讲,退出是由高度异步的事件启动的,用户关闭用户界面,管理员关闭计算机,等等。 这种情况的发生与程序启动的线程的状态无关,它们几乎总是处于高度不可预测的状态。

在理想情况下,程序的 main(( 函数要求线程退出,通常通过发出事件信号,等待线程结束,然后退出 main(( 以通过 exit(( 干净关闭。 然而,这一理想很难实现。 线程可能深埋在系统调用中,例如,等待某些 I/O 完成。 或者它阻塞了需要由另一个线程以正确顺序发出信号的同步对象。 结果很少令人愉快,真正的程序往往在退出时陷入僵局。 或者在关闭命令意外时崩溃。

对于此问题,有一个简单且非常诱人的解决方法:改为调用 _exit((。 卡布姆,程序结束,操作系统扫除弹片。 但显然根本没有任何清理,有时会非常混乱,例如半写的文件或不完整的 dbase 事务。

std::quick_exit(( 提供了替代方案。 与 _exit(( 类似,但仍然可以选择执行一些代码,无论在 at_quick_exit 中注册了什么。

std::quick_exit的基本原理在 N1327 和 N2440 中讨论。quick_exit_Exitexit 之间的主要区别在于静态析构函数的处理和将关键信息刷新到稳定存储:

  • std::_Exit:不执行静态析构函数或刷新关键 IO。
  • std::exit:执行静态析构函数并刷新关键 IO。
  • std::quick_exit:不执行静态析构函数,但刷新关键 IO。

(如前所述,std::abort只是发送SIGABRT

>std::abort将终止您的应用程序,而不会调用使用"at_exit/at_quick_exit"注册的任何函数。另一方面,正如您所指出的,std::quick_exit将调用使用 std::at_quick_exit 注册的函数。

std::abort通常会中止应用程序,但在发生某些异常情况并且必须关闭应用程序而不执行任何清理时,应调用此选项。从std::abort文档中:

导致程序异常终止,除非 SIGABRT 被捕获 传递给 Signal 的信号处理程序,并且处理程序不返回。

当您要执行一些清理时,std::quick_exit会更合适。最后一个函数还允许您优雅地停止应用程序,因为它最终会调用std::_Exit而不是像 std::abort 这样的信号(发出信号 SIGABRT,使应用程序异常停止(。

std::exit允许您优雅地退出应用程序,同时仍然清理自动、线程局部和静态变量。 std::quick_exit没有。这就是为什么它的名字中有一个"quick_",它更快,因为它跳过了清理阶段。

因此,这两个函数之间存在实际的语义差异。一个异常停止应用程序,另一个执行正常退出,允许您执行一些清理。