内存泄漏到什么程度?

我遇到过很多次内存泄漏。通常,当我像没有明天一样的 malloc或者像脏衣服一样悬挂 FILE *的时候。我通常假设(阅读: 绝望的希望) ,所有的内存是清理至少当程序终止。当程序终止或崩溃时,是否存在无法收集泄漏内存的情况?

If the answer varies widely from language-to-language, then let's focus on C(++).

请注意这个短语的双曲用法,“就像没有明天”,和“悬挂... 就像脏衣服”。不安全的行为会伤害你爱的人。此外,请小心使用脏衣服。

9457 次浏览

操作系统在进程退出时释放它们所持有的所有资源。

这适用于操作系统维护的所有资源: 内存、打开的文件、网络连接、窗口句柄..。

That said, if the program is running on an embedded system without an operating system, or with a very simple or buggy operating system, the memory might be unusable until a reboot. But if you were in that situation you probably wouldn't be asking this question.

The operating system may take a long time to free certain resources. For example the TCP port that a network server uses to accept connections may take minutes to become free, even if properly closed by the program. A networked program may also hold remote resources such as database objects. The remote system should free those resources when the network connection is lost, but it may take even longer than the local operating system.

C 标准没有指定在程序终止时释放由 malloc分配的内存。这是由操作系统完成的,并不是所有的操作系统(通常是嵌入式系统)在程序终止时释放内存。

这更可能取决于操作系统而不是语言。最终,任何语言的任何程序都会从操作系统获得内存。

我从未听说过一个操作系统在程序退出/崩溃时不能回收内存。所以如果程序需要分配的内存有上限,那么只分配而不释放是完全合理的。

所有值得称道的操作系统都将清理终止后您的进程造成的混乱。但是总是有不可预见的事件,如果它被拒绝访问以某种方式和一些可怜的程序员没有预见到的可能性,所以它不再尝试一点以后呢? 如果内存泄漏对任务至关重要,那么自己清理总是更安全——否则,如果代价高昂,那么 IMO 的努力就不值得了。

编辑: 如果内存泄漏位于它们将要累积的位置(如循环中) ,则确实需要清理内存泄漏。我所说的内存泄漏是指在整个程序过程中不断积累的内存泄漏,如果您有任何其他类型的内存泄漏,那么它很可能迟早会成为一个严重的问题。

In technical terms if your leaks are of memory 'complexity' O(1) they are fine in most cases, O(logn) already unpleasant (and in some cases fatal) and O(N)+ intolerable.

正如其他人所说,大多数操作系统会在进程终止时回收已分配的内存(可能还有其他资源,如网络套接字、文件句柄等)。

尽管如此,在处理 new/delete (而不是原始的 malloc/free)时,内存可能不是唯一需要担心的事情。在 new 中分配的内存可能会被回收,但是在对象的析构函数中所做的事情不会发生。也许某个类的析构函数在销毁时将一个哨兵值写入到文件中。如果进程刚刚终止,文件句柄可能会被刷新并回收内存,但是不会写入哨兵值。

这个故事的寓意是,永远把自己打扫干净。不要让事情悬而未决。不要指望操作系统帮你收拾残局。自己收拾干净。

如果程序被转换成一个动态组件(“ plugin”) ,并被加载到另一个程序的地址空间中,那么即使在内存管理整洁的操作系统上,也会很麻烦。我们甚至不必考虑将代码移植到能力较差的系统上。

另一方面,释放所有内存 可以会影响程序清理的性能。

我正在研究的一个程序,某个测试用例需要30秒或更长时间才能退出,因为它在所有动态内存的图形中循环,并一块一块地释放它。

一个合理的解决方案是在那里拥有该功能,并用测试用例覆盖它,但在生产代码中将其关闭,以便应用程序快速退出。

因为所有的答案已经涵盖了你的问题的大部分方面,但是从历史上来看,有一个值得一提,如果你曾经在 DOS 世界编程。终结者和居民(TSR)程序通常会将控制返回给系统,但是会驻留在内存中,这些内存可以通过软件/硬件中断恢复。在操作这些操作系统时,看到像 “内存不足! 试着卸载一些 TSR”这样的消息是很正常的。

因此,从技术上讲,程序终止,但因为它仍然驻留在内存,任何内存泄漏将不会释放,除非您卸载该程序。

因此,您可以认为这是操作系统没有回收内存的另一种情况,或者是因为存在错误,或者是因为嵌入式操作系统就是这样设计的。

我还记得一个例子。主要在 IBM 大型机上运行的事务服务器 客户信息控制系统(CICS)是伪会话的。执行时,它处理用户输入的数据,为用户生成另一组数据,传输到用户终端节点并终止。在激活注意力键时,它再次苏醒,处理另一组数据。由于它的行为方式,从技术上来说,操作系统不会从终止的 CICS 程序中回收内存,除非您回收 CICS 事务服务器。

If you have interprocess communication, this can lead to other processes never completing and consuming resources depending on the protocol.

举个例子,我曾经在 Java 中尝试打印到 PDF 打印机,当我在打印机作业中间终止 JVM 时,PDF 假脱机进程仍然处于活动状态,我必须在任务管理器中终止它,然后才能重试打印。

符合 POSIX 的系统上的共享内存将持续存在,直到调用 shm _ unlink 或重新启动系统。