malloc 和朋友的基本工作是管理这样一个事实:操作系统通常只能(有效)处理大型分配(整个页面和页面范围),而程序通常需要更小的块和更细粒度的管理。
因此,malloc(通常)的作用是,第一次调用它时,它会从系统分配大量内存(通过 mmap 或 sbrk——可能是一页,也可能是许多页),并使用其中的少量内存。对于某些数据结构来说,可以跟踪堆的使用情况(堆在哪里、哪些部分正在使用以及哪些部分空闲),然后将该空间的其余部分标记为空闲。然后,它从该可用空间中分配您请求的内存,并保留其余部分以供后续 malloc 调用使用。
因此,第一次调用 malloc 例如 16 字节时,它将使用 mmap 或 sbrk 分配一个大块(可能是 4K 或可能 64K 或可能 16MB 甚至更多)并将其初始化为大部分空闲,并返回一个指向 16 字节的指针某处。第二次调用 malloc 获取另外 16 个字节只会从该池中返回另外 16 个字节 - 无需返回操作系统获取更多信息。
当您的程序继续分配更多内存时,它将来自该池,并且免费调用会将内存返回到空闲池。如果它通常分配的内存多于释放的内存,最终该空闲池将耗尽,此时,malloc 将调用系统(mmap 或 sbrk)来获取更多内存以添加到空闲池中。
这就是为什么如果您使用某种进程监视器监视使用 malloc/free 分配和释放内存的进程,您通常只会看到内存使用量上升(因为空闲池耗尽并且从系统请求更多内存) ),并且通常不会看到它下降——即使内存被释放,它通常只是返回到空闲池,并且不会取消映射或返回到系统。有一些例外 - 特别是如果涉及非常大的块 - 但通常您不能依赖任何内存返回到系统,直到进程退出。