内存泄漏能走多远?
我多次遇到内存泄漏。 通常当我是malloc-像没有明天,或悬挂FILE *
s像脏衣服。 我通常假设(阅读:绝望地希望)所有内存至less在程序终止时被清除。 当程序终止或崩溃时,有没有泄漏的内存不会被收集的情况?
如果答案从语言到语言的差别很大,那么让我们关注C(++)。
请注意这句话的双曲线用法,“就像没有明天”,“摇摆不定……像脏衣服”。 不安全* malloc
* ing会伤害你所爱的人。 另外,脏衣服请小心。
不可以。操作系统退出时释放进程所拥有的所有资源。
这适用于操作系统维护的所有资源:内存,打开的文件,networking连接,窗口句柄…
也就是说,如果程序在没有操作系统的embedded式系统上运行,或者运行在非常简单或者有问题的操作系统上,那么内存在重新启动之前可能无法使用。 但是,如果你是在这种情况下,你可能不会问这个问题。
操作系统可能需要很长时间来释放某些资源。 例如,networking服务器用于接受连接的TCP端口可能需要几分钟才能变为空闲,即使程序正确closures了该端口。 联网程序也可以保存远程资源,如数据库对象。 当networking连接丢失时,远程系统应该释放这些资源,但可能比本地操作系统需要更长的时间。
C标准没有指定程序终止时由malloc
分配的malloc
被释放。 这是由操作系统完成的,而不是所有的操作系统(通常是embedded式系统)在程序终止时释放内存。
由于所有的答案都涵盖了现代操作系统的问题的大部分方面,但是从历史上看,如果您曾经在DOS世界中编程过,那么就值得一提。 终止和居留 (TSR)程序通常会将控制权交还给系统,但是会驻留在内存中,可以通过软件/硬件中断来恢复。 在这些操作系统上工作时,看到像“内存不足!尝试卸载一些TSR”的消息是正常的。
所以从技术上说, 程序终止 ,但是因为它仍然驻留在内存中,除非卸载程序,否则任何内存泄漏都不会被释放。
所以你可以认为这是另一种情况,除了操作系统不回收内存,或者是因为它有问题,或者是因为embedded式操作系统被devise为这样做。
我还记得一个例子。 客户信息控制系统 (CICS)是一种主要在IBM大型机上运行的事务处理服务器,是伪对话式的。 当执行时,它处理用户input的数据,为用户生成另一组数据,传送到用户terminal节点并终止。 在激活注意键时,它再次恢复处理另一组数据。 由于它的行为方式,在技术上,操作系统不会从已终止的CICS程序中回收内存,除非您循环使用CICS事务服务器。
像其他人所说的那样,大多数操作系统在进程终止时(以及可能的其他资源,如networking套接字,文件句柄等)将回收分配的内存。
话虽如此,在处理new / delete(而不是原始malloc / free)时,内存可能不是唯一需要担心的事情。 在new中分配的内存可能会被回收,但是在对象的析构函数中可能会做的事情不会发生。 也许某些类的析构函数在销毁时将一个标记值写入文件中。 如果进程刚刚结束,则文件句柄可能会被刷新并回收内存,但该标记值不会被写入。
道德的故事,总是自己清理。 不要让事情悬而未决。 之后不要依靠操作系统清理。 自己清理。
这更可能取决于操作系统而不是语言。 最终,任何语言的程序都将从操作系统获取内存。
我从来没有听说过一个程序退出/崩溃时没有回收内存的操作系统。 所以如果你的程序需要分配内存的上限,那么只要分配,永不释放是完全合理的。
如果程序变成了一个dynamic的组件(“插件”),它被加载到另一个程序的地址空间中,即使是在操作系统上有整洁的内存pipe理的情况下也是很麻烦的。 我们甚至不必考虑将代码移植到性能较差的系统上。
另一方面,释放所有内存可能会影响程序清理的性能。
我正在研究一个程序,某个testing用例需要30秒或更长时间才能退出程序,因为它是通过所有dynamic内存的图表recursion并逐一释放的。
一个合理的解决scheme是在那里有能力并且覆盖testing用例,但是在生产代码中closures它,这样应用程序就会快速退出。
所有值得称号的操作系统将清理终止后您的stream程。 但总会有一些无法预料的事情发生,如果某种程度上被拒绝了,一些可怜的程序员没有预见到这种可能性,所以稍后再试一次呢? 总是要安全的清理自己,如果内存泄漏是关键的任务 – 否则不是真的值得IMO努力,如果这种努力是昂贵的。
编辑:你需要清理内存泄漏,如果他们在他们将积累的地方,就像循环。 我所说的内存泄漏是在整个程序过程中不断积累的内存泄漏,如果你有任何其他types的泄漏,迟早会很可能是一个严重的问题。
从技术angular度来讲,如果你的泄漏具有记忆“复杂性”O(1),在大多数情况下,O(logn)已经很不愉快(在某些情况下是致命的)和O(N)+是不能容忍的。
POSIX兼容系统上的共享内存一直存在,直到调用shm_unlink或系统重新启动。
如果您有进程间通信,这可能会导致其他进程永远不会完成和消耗资源取决于协议。
举个例子,当我在打印机作业中间终止JVM时,曾经尝试用Java打印到PDF打印机,PDF假脱机过程保持活跃,我必须在任务pipe理器中杀死它,然后才能重试打印。