我有一些“全局”构造,它们使用new分配,整个应用程序的生命周期都存在。
在应用程序完成之前是否需要打扰调用指针上的delete呢?毕竟,当应用程序关闭时,所有应用程序的内存不是都会被回收吗?
为了更清晰地说明,我仅讨论那些在程序关闭时“死亡”的生命期对象不需要调用delete的情况。
我有一些“全局”构造,它们使用new分配,整个应用程序的生命周期都存在。
在应用程序完成之前是否需要打扰调用指针上的delete呢?毕竟,当应用程序关闭时,所有应用程序的内存不是都会被回收吗?
为了更清晰地说明,我仅讨论那些在程序关闭时“死亡”的生命期对象不需要调用delete的情况。
从技术上讲,是的,内存被回收了。但是,除非您使用delete
,否则这些对象的析构函数不会运行,它们的副作用也不会应用。这可能会导致临时文件未被删除或数据库更改未被提交,具体取决于那些析构函数的意图。
此外,还要记住墨菲定律。现在用于管理这些对象的代码是按照您描述的方式使用的(对象必须持续存在于程序的生命周期中),但以后您可能希望重用该代码,使其多次运行。除非它能正确地处理重新创建对象,否则它将泄漏对象。
无论如何,清理一切都是一个好的实践。尽管内存被释放了,这些对象可能会分配其他资源(共享内存、信号量等),应该通过对象的析构函数进行清理。
如果您不想调用delete,请使用共享指针来持有这些资源,以便在应用程序退出时正确清理它们。
您如何测试您的应用程序?不清理可能会妨碍开发一个体面的测试工具。应用程序的测试可能需要一种欺骗性关闭和重新启动的方法。
清理工作不仅仅是简单地释放内存。
我认为你可能是对的,但我个人认为依赖系统并且不保证代码在关闭时始终整洁是糟糕的编码和不良实践。
没有一个正确的答案。大多数情况下,这可能并不重要,但是有些析构函数会执行一些重要的操作,而不仅仅是释放内存(我有一个析构函数用于删除临时文件),这支持清理的论点;另一方面,如果这些对象被其他对象的析构函数使用,则析构此类对象可能会导致销毁顺序问题。我的一般规则是不进行析构,除非析构函数执行的操作不仅仅是释放内存,但是其他人可能更喜欢不同的默认设置。
new
创建对象,但却没有使用delete
释放。如果这个库被重复加载/卸载(使用dlopen
/LoadLibrary
等),你实际上会不断地泄漏更多的资源。你必须通过编写代码、测试和维护来处理这个问题。 - Frerich Raabe然后还有那些情况,你绝对不希望在操作系统终止进程之前调用dtor,例如:
1)当dtor无法正常工作时,因为它试图终止一个线程,失败并阻塞在线程句柄或其他信号上(永恒的“join/waitFor”死锁),这是所有家庭“我的应用程序无法干净地关闭”的帖子的99%的原因。
2)当dtor无法正常工作时,因为它本身就很糟糕,并且被埋在库中。
3)当内存必须比进程线程更长寿时,否则在关闭时会出现segfaults/AV(例如,缓冲对象池,线程可能会在关闭时写入)。
4)任何其他需要将对象的销毁留给操作系统的“特殊情况”。
有这么多“特殊情况”,我认为“清理”关闭代码是特例。