为什么使用exit()被认为是不好的?

10

我正在阅读这个问题,其中有一个回答解释了为什么使用exit()是不好的,因为:

  • 你将会结束程序中有多个退出点
  • 它使代码更加混乱(类似于使用goto)
  • 它不能释放在运行时分配的内存

我应该澄清一下,我正在使用Qt,所以代码已经有点“混乱”,因为我正在利用信号和槽。话虽如此,对于问题#1,我看到它与#2有关,但我的代码目前试图避免使用exit(),因为我被告知它会使我的代码看起来很混乱,但避免使用exit却让它变得混乱。例如,当用户注册并且他们的用户名已经存在时,我不仅告诉用户注册失败(这是期望的行为),还返回false给一个函数,然后返回false给另一个函数,然后再返回false给我的主函数,如果它返回false,则返回0。所以,避免使用exit()根本无法使代码更加清晰。

对于第三个问题,使用exit(0)不是告诉操作系统程序已经完成运行,操作系统会自动释放那些内存吗?当我按下按钮并使用exit(0)时,我测试了一个案例,该进程从进程列表中被移除,并且内存被释放,那么这还有什么问题呢?至少在Windows上,这似乎是一个彻头彻尾的错误陈述。


操作系统无法清理所有内容。想象一下一个终止在线连接的析构函数,或者一个将文本刷新到日志文件中的析构函数。对于析构函数可以发生什么,操作系统非常有限。 - chris
3
那简直是错误的 - 几乎所有的操作系统都会尽可能地“清理”你的资源 - 绑定到进程的套接字将被销毁,文件将被关闭等等。但它无法清理你的进程中潜在的、无效的数据 - 如果进程在写完所有数据之前就结束了...呃...显然会发生什么。 - specializt
1
是的 - 在那之后,大多数古老的人(创建第一个操作系统的人)每天都会像这样创建程序。它被称为“过程式编程”。不太可读,有些容易出错,总体上很丑陋,不建议使用,但它确实有效。 - specializt
关闭一个问题并将其标记为最近的重复问题是不寻常的,但新问题有一些很好的答案。 - Jonathan Leffler
@JonathanLeffler:是的,新问题有一些很好的答案。然而,它并没有展示更快的退出何时以及如何可能和/或建议。 - Deduplicator
显示剩余6条评论
2个回答

16

在程序的某个地方盲目调用 exit() 被认为是不好的一个简单原因是:

它不能正确关闭其他线程(它们只是被终止了),它不能正确地刷新所有缓冲区(stdio文件会被刷新)并保证永久/共享资源(文件/共享内存/其它通信方式)的一致和有效状态。

然而,如果你可以确保没有运行的线程可能会干扰(通过被杀死保持锁定或类似方式),并且所有需要刷新的缓冲区都将被 exit() 刷新,那么这是实现更快关闭的有效方法。

许多现代软件都是为了更快的关闭而编写的:

它具有崩溃容错性,在几乎任何时候,只需使用例如 _Exit() (甚至不调用注册的 atexitat_quick_exit 钩子)来关闭就可以了。在大多数情况下,这比有序的关闭要快得多(如果可能应首先销毁 Windows 用户界面资源,因为它们是一个例外)。

更多阅读:仅崩溃的软件(PDF!)

仅崩溃的程序可以安全地崩溃并快速恢复。停止这种软件只有一种方法-通过崩溃-并且启动它的唯一方法是通过启动恢复。崩溃式系统由崩溃组件构建,并且透明的组件级重试使用从最终用户中隐藏了 intra-system 组件崩溃。在本文中,我们主张为互联网系统采用崩溃设计,以表明它可以导致更可靠,可预测的代码和更快,更有效的恢复。我们提出了如何构建这样的仅崩溃互联网服务的想法,将成功的技术推向其逻辑极限。


哪些用户界面资源必须显式地销毁?在进程终止后,Windows难道不会回收所有这些对象吗? - Ruslan
@Ruslan 是的,Windows会回收它们。但是相比你自己显式地清理它们,这可能会更慢(或者曾经更慢)。 - Deduplicator

0

我不同意第1和第2项。那些更多是风格和偏好的问题。

至于第3项,你应该查看文档以了解它实际上会或不会释放或刷新什么(http://en.cppreference.com/w/cpp/utility/program/exithttp://msdn.microsoft.com/en-us/library/6wdz5232.aspx)。例如,MS文档说“在终止进程之前刷新所有文件缓冲区。”

当你的程序退出时,操作系统将回收内存,但这不是他所说的。他的意思是像信号量这样的资源不会被适当地或及时地释放。也许这是一个问题,也许不是,这取决于你使用的资源类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接