当代码无法释放内存时,它是不是是 C 中的内存泄漏,但操作系统仍然会?

Posted

技术标签:

【中文标题】当代码无法释放内存时,它是不是是 C 中的内存泄漏,但操作系统仍然会?【英文标题】:Is it a memory leak in C when code fails to free memory, but the OS will anyway?当代码无法释放内存时,它是否是 C 中的内存泄漏,但操作系统仍然会? 【发布时间】:2020-04-01 14:52:54 【问题描述】:

假设我有以下程序仅用于演示目的:

#include <stdio.h>
#include <stdlib.h>

int main(void)

    char *my_memory = malloc(50000);
    int *my_int = malloc(sizeof(int));
    
    //Do other things but never free my_memory or my_int
    
    return 0;

根据Wikipedia:

在计算机科学中,内存泄漏是一种资源泄漏,当计算机程序错误地管理内存分配1 以致不再需要的内存不会被释放时,就会发生这种情况。当对象存储在内存中但运行代码无法访问时,也可能发生内存泄漏。[2]

第 1 句暗示内存泄漏可能是不需要的、未释放的内存。但是,与我共事过的很多程序员都表示“没有内存泄漏,因为操作系统会释放内存”。这些程序员认为只有在不再有某个分配的引用点或句柄时才会发生内存泄漏,从而使其不再可访问且不再能够被释放。

据我所知,对于现代 macOS、Windows 和 Linux,操作系统确实会释放内存。

我使用过 AddressSanitizer、Dr. Memory 和 Valgrind;他们将此类程序标记为“内存泄漏”。

所以我的问题是,像上面这样的例子,在程序终止之前分配了内存而不是释放,是否存在内存泄漏?

【问题讨论】:

***.com/questions/273209/are-memory-leaks-ever-ok @Mat 虽然讨论类似,但我的问题根本不同 - 它涉及实际接受的内存泄漏定义,而不是 一旦确定,就是内存那么在某些情况下泄漏是否可以接受? 没有公认的定义 - 您已经在您的问题中发现了这一点。 @Mat 我认为这里的真正问题可以归结为 - “内存泄漏是从进程的角度来看,还是从包括操作系统在内的整个系统的角度来看?”我认为不可能同时“是”和“否”,但例如,当程序被视为独立系统时,它是“是”。当操作系统是图片的一部分时,它是“不”。 【参考方案1】:

是和不是。

大多数程序的编写都期望在终止之前释放内存。但是大多数操作系统被编写为不对应用程序使用的内存进行任何假设,因此它们确实会在程序终止后回收该内存。

并不是说在您的应用程序代码中释放内存总是直接将其返回给操作系统——典型的内存分配器只会将内存标记为未使用并在随后对malloc()的调用中可用。

还有一些程序以不释放分配的内存为目的而编写。这是实现高性能释放的一种简单有效的方法,因为操作系统将分配的内存视为少量大块,并且与应用程序显式释放每个块相比,释放这些块所需的时间要少得多(假设从应用程序的角度来看,它们被分配为大量的小对象)。这是一种有效的方法,尽管它确实使一些分析工具(如 valgrind)的使用变得复杂,因此一些程序通过显式分配和释放少量大型内存“池”并在内部将它们划分为存储小对象来避免它。这种“池分配器”方法类似于 C 标准 malloc()free() 通常为您所做的。

【讨论】:

【参考方案2】:

是的,这是内存泄漏。 每次分配空间时,都必须在不再需要时释放该空间。 由于分配的内存可以在线程之间共享,因此操作系统很难检测到没有更多的程序不再使用该空间,并且在程序结束后仍会分配它。

【讨论】:

以上是关于当代码无法释放内存时,它是不是是 C 中的内存泄漏,但操作系统仍然会?的主要内容,如果未能解决你的问题,请参考以下文章

iphone App中的内存泄漏

Android 中的内存泄漏和内存溢出

Linux下内存泄漏工具

什么是内存泄漏?

C ++中的内存泄漏示例(通过使用异常)[重复]

Java内存管理——垃圾收集