繁体   English   中英

使用malloc进行页面分配时发生内存泄漏

[英]Memory leak on page allocation with malloc

考虑以下C代码,该代码创建100,000个4KB大小的页面,然后释放99,999页,最后释放最后一页:

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

#define NUM_PAGES 100000

int main() {
    void *pages[NUM_PAGES];

    int i;
    for(i=0; i<NUM_PAGES; i++) {
        pages[i] = malloc(4096);
    }

    printf("%d pages allocated.\n", NUM_PAGES);
    getchar();

    for(i=0; i<NUM_PAGES-1; i++) {
        free(pages[i]);
    }

    printf("%d pages freed.\n", NUM_PAGES-1);
    getchar();

    free(pages[NUM_PAGES-1]);

    printf("Last page freed.\n");
    getchar();

    return 0;
}

如果您对其进行编译,运行并监视进程的内存使用情况,则可以看到在第一个getchar之前(当内存分配给100,000页时)内存使用量达到了约400MB,然后即使删除了99,999页,它也保持不变。 -allocated(在第二个getchar ),最后,当最后一个页面被取消分配时,它下降到1MB。

所以,我的问题是为什么会这样? 为什么只有释放所有页面后,整个内存才返回给OS? 是否有任何页面尺寸或任何页面对齐方式可防止此类情况发生? 我的意思是,只有一个页面被释放时,是否有任何页面大小或对齐方式可使任何分配的页面完全返回操作系统?

这完全取决于实现,但是我认为这与内存分配器的工作方式有关。 通常,当内存管理器需要从操作系统获取更多内存时,它将调用sbrk函数以请求更多内存。 此功能的典型实现是OS将指针存储到内存中下一个可用地址的指针,进程可以在其中获得空间。 内存就像堆栈一样增长,与调用堆栈的工作方式非常相似。 例如,如果您分配了五个页面的内存,则可能如下所示:

 (existing memory) | Page 0 | Page 1 | Page 2 | Page 3 | Page 4 | (next free spot)

使用此设置,如果您释放0-4页,则程序内的内存管理器会将其标记为空闲,如下所示:

 (existing memory) |                                   | Page 4 | (next free spot)

由于OS以类似堆栈的方式分配内存,因此在使用完第4页之前,它无法从程序中回收所有这些内存。 一旦释放了最后一页,进程的内存将如下所示:

 (existing memory) |                                              (next free spot)

此时,程序的内存管理器可以将大量可用空间返回给操作系统:

 (existing memory) | (next free spot)

换句话说,由于内存是作为堆栈分配的,因此在取消分配所分配的最后一件事之前,操作系统无法回收任何内存。

希望这可以帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM