首页 > 解决方案 > 当代码无法释放内存时,它是否是 C 中的内存泄漏,但操作系统仍然会?

问题描述

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

#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;
}

根据维基百科

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

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

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

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

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

标签: cmemorymemory-leaks

解决方案


是和不是。

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

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

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


推荐阅读