在程序结束时调用析构函数为什么很重要?

4
如果您查看此链接http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=107 ,它写道:

“例如,无论在调试期间还是在其他情况下,在面向对象的环境中都不得使用abort()和exit()库函数,因为它们不会在程序终止之前调用对象的析构函数。”

为什么需要在调用exit时调用析构函数?(因为操作系统在程序退出时保证会回收内存,对吗?)


3
这是一个极具误导性的陈述:“OO -> !abort && !exit,(因为X)”,而应该简单地说“X -> !abort && !exit”。 OO与问题完全无关:例如,过程化代码同样有清理代码需要在终止前调用... - Tony Delroy
2
这也是误导性的,因为exit确实调用命名空间范围、局部静态和静态类成员对象的析构函数。 - Johannes Schaub - litb
2个回答

9
析构函数除了释放内存和/或资源外,通常还会执行其他操作。它们经常用于提供某些其他保证,例如将用户数据写入文件或确保非进程特定资源处于已知状态。在退出时,操作系统不会执行这些类型的操作。
话虽如此,任何依赖于这些类型操作的程序都是基本有缺陷的。使用 exit 和 abort 不是避免析构函数的唯一方法。还有许多其他方式可以规避析构函数。例如,用户强制终止进程或停电。
我绝对不同意引用段落中使用“永远”这个词。我想到至少一种情况,您绝对不希望执行析构函数:内存损坏。当您检测到内存损坏时,您无法再对进程中的代码(包括析构函数)做出任何保证。应该将数据写入文件的代码可能会删除/破坏它。
当检测到内存损坏时,唯一安全的做法是尽快退出进程。

1
无论析构函数是否被调用,我不建议通过断电来终止程序。 :) - Justin Ardini
@Justin,也许不是断电,但当我向挂起的操作系统报仇时,我肯定很高兴地取出了我的笔记本电池。 - JaredPar
1
这在某种程度上取决于依赖的类型。如果我们说“我将尝试保存用户的数据”,那么依靠析构函数来实现这一点并不根本上有错误 - 好吧,在停电时你无法保存,但这可能是可以接受的,因为你无法保存。所以除非无法保存(如出现损坏),否则在该程序中应避免使用 abort(),同样避免刷新stdout等。如果我们说,“用户的保存文件将暂时处于不可恢复状态,并且析构函数将其还原到有效状态”,那么这个程序就存在根本性缺陷。 - Steve Jessop
@Steve,我同意尝试并不是问题,只要您不依赖于它发生。 - JaredPar

0
首先,我想建议大家“不要盲目相信你所读到的任何东西”。
可能像JaredPar所说的那样,析构函数可能会执行一些记录信息和关闭操作系统资源句柄的事情。如果您调用了abort或exit,这些事情将永远不会发生。
但是,我确实不完全同意这句话。在开发周期中,Abort是查找编程错误的最佳和最快捷的方法。作为一个开发者,您当然不会在代码中随便放置abort,而是在条件下知道永远不应该发生的情况下放置abort。当您知道其他程序员或您已经在代码中犯下了错误,停止比处理错误更好时,您会放置abort。我曾经遇到过一个情况,其中abort真的挽救了我的生命。

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