【问题标题】:Why is it important to call destructors at program termination?为什么在程序终止时调用析构函数很重要?
【发布时间】:2023-03-20 15:28:01
【问题描述】:

如果您检查此链接http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=107 它是这样写的:

“例如,abort() 和 exit() 库函数永远不能在面向对象的环境中使用——即使在调试期间也是如此——因为它们不会在程序终止之前调用对象的析构函数。”

为什么一个调用退出时需要调用析构函数? (既然操作系统保证程序退出时内存会被回收,对吧?)

【问题讨论】:

  • 这是一个非常具有误导性的陈述; “OO -> !abort && !exit, (because X)”,当它应该简单地说“X -> !abort && !exit”时。 OO 与该问题完全无关:例如,程序代码很可能在终止前调用清理代码......
  • 这也是一种误导,因为exit确实调用了命名空间范围和本地静态和静态类成员对象的析构函数。

标签: c++


【解决方案1】:

首先,我想建议“不要盲目相信你读过的任何东西”。 可能正如 JaredPar 所说,析构函数可能会做一些日志记录和关闭操作系统资源处理的事情。如果您调用 abort 或 exit,这些事情将永远不会发生。

但我当然完全不同意这句话。 Abort 是在开发周期中查找编程错误的最好和最快的方法。作为一名开发人员,您当然不会盲目地在代码中到处使用 abort,但前提是您知道这不应该发生。当你知道其他程序员或者你在代码中的某个地方搞砸了,你就放弃了,最好停止而不是处理错误。我曾经经历过 abort 真的救了我的@$$ 的情况。

【讨论】:

    【解决方案2】:

    除了释放内存和/或资源之外,析构函数还可以并且经常执行其他操作。它们通常用于做出某些其他保证,例如将用户数据写入文件或非进程特定资源处于已知状态。操作系统不会在退出时执行这些类型的操作。

    话虽如此,任何依赖这些类型操作的程序都存在根本缺陷。使用 exit 和 abort 并不是避免析构函数的唯一方法。还有许多其他方法可以绕过析构函数。例如用户强行终止进程或断电。

    我绝对不同意在引用的段落中使用 never。我至少可以想到一种绝对不希望执行析构函数的情况:损坏的内存。在您检测到损坏的内存时,您无法再对进程中的代码做出任何保证,包括析构函数。应该将数据写入文件的代码可能会删除/损坏它。

    当检测到内存损坏时,唯一安全的做法是尽快退出进程。

    【讨论】:

    • 无论是否调用析构函数,我都不建议通过断电来终止程序。 :)
    • @Justin,也许不是停电,但当我对挂起的操作系统进行报复时,我肯定高兴地取出了笔记本电脑的电池。
    • 这取决于依赖的类型。如果我们说“我会尝试保存用户的数据”,那么依靠析构函数来执行此操作并没有根本性的缺陷 - 好的,停电时您不会保存,但这可能是允许的,因为没有你可以保存的方式。因此,您应该避免在该程序中使用abort(),除非无论如何都无法保存,因为它会损坏。同样刷新stdout等。如果我们说“用户的保存文件将暂时处于不可恢复状态,而析构函数会将其恢复到有效状态”,那么程序基本上是有缺陷。
    • @Steve,我同意尝试不是问题,只要你不依赖它发生
    猜你喜欢
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    • 2021-08-04
    • 2019-11-16
    • 1970-01-01
    • 2021-07-01
    相关资源
    最近更新 更多