【问题标题】:should we use exit in C++?我们应该在 C++ 中使用 exit 吗?
【发布时间】:2016-08-19 14:25:38
【问题描述】:

根据C++参考​​p>

exit 正常终止进程,执行定期清理 用于终止程序。

正常程序终止执行以下操作(以相同的顺序): 与具有线程存储的当前线程关联的对象 持续时间被销毁(仅限 C++11)。具有静态存储的对象 持续时间被破坏(C ++)并且用atexit注册的函数是 叫。所有 C 流(使用 中的函数打开)都已关闭 (如果缓冲,则刷新),并且使用 tmpfile 创建的所有文件都是 删除。控制权返回到宿主环境。

请注意,具有自动存储功能的对象不会通过调用来销毁 退出 (C++)。

据我所知,当进程终止时,进程使用的所有存储都被回收,那么自动存储的对象不被销毁有什么影响?

【问题讨论】:

  • 如果在函数调用 exit() 时自动范围保护变量正在锁定互斥锁,则该互斥锁将不会被解锁,并且如果执行了任何终止清理(对于线程/静态变量, atexit...) 想要锁定相同的互斥锁,它可能会死锁并阻止干净关闭。
  • 标准是说 C++ 运行时所做的一切都被撤消了。它没有说明您的应用程序。它不能确保您的应用程序自行清理。

标签: c++ c++11 exit


【解决方案1】:

如果不调用这些析构函数,它们的副作用就不会发生:释放其他进程中的资源、删除该文件夹外的临时文件、刷新非 c 流文件等

【讨论】:

    【解决方案2】:

    问题在于,并非您可能以某种方式拥有的所有东西都在标准中被列为正在清理。

    例如,许多程序和库会执行创建锁定文件、启动后台进程、更改系统设置等操作。如果您调用exit,这些可能会被操作系统清理,但它们不是必须的。未能释放这些可能会产生各种影响,从无法重新启动程序(典型的锁定文件)到整个系统故障(不太可能,但在某些情况下可能)。

    没错,关于主题的轶事。我曾经在我的项目中使用输入库 OIS。每次我在调试器中杀死我的程序时,系统范围内的重复键都会被破坏,因为 OIS 在 Linux 中“暂时”禁用了它。我通过更改设置(后来完全转储 OIS)修复了它,但这很好地说明了在您自己清理环境之前调用 exit 可能会遇到的问题。

    【讨论】:

    • 我还有一个问题:如果退出不是一个好的选择,我可以用什么来停止 C++ 中的子进程?
    • @xlnwel 并不是exit 本身不好,而是取决于exit 的清理行为不好。只要你事先清理资源,exit 应该没问题,就像 main()return 一样。因此,只要确保您处于终止状态,请随意使用它。通常,简单地让main() 返回是结束程序的首选方式,但我并不真正熟悉进程的工作方式,至少在一般/跨平台上,所以如果exit 在这种情况下有用,请使用它 - 只是小心。
    【解决方案3】:

    在 C++ 中,您最好使用 std::terminate 而不是 exitabort 来执行有序的致命错误退出,因为您正在使用的代码可能已经安装了 terminate handler 来执行关键清理。

    默认的std::terminate 处理程序调用abort

    堆栈没有展开。

    回复

    自动存储的对象不被销毁有什么影响?

    因为没有调用析构函数,所以不会执行它们可能执行的清理操作。例如,在 Windows 中,如果控制台窗口具有自定义文本缓冲区,它可能会变得不可用。临时文件可能留在磁盘上。辅助进程可能不会关闭。以此类推。

    这必须考虑到如果尝试进行一般清理可能会发生令人讨厌的事情,例如因为断言已触发,表明有关进程状态的一些基本假设不成立。

    【讨论】:

    • 感谢您的回答,现在退出不安全,并且您所描述的 std::terminal 在 C++ 中似乎也不安全,我可以使用什么来安全地停止子进程?
    • @xlnwel:为了完全安全,您需要子进程的一些合作。例如。它会在短时间内检查信号。 C++ 标准库不提供进程间通信的任何方式(文件系统除外),因此您可能需要使用系统特定的功能。
    猜你喜欢
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    相关资源
    最近更新 更多