简体   繁体   English

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

[英]Memory leak on page allocation with malloc

Consider the following C code, which creates 100,000 4KB-sized pages, then frees 99,999 pages and, finally, frees the last page: 考虑以下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;
}

If you compile it, run it and monitor the process' memory usage, you can see that the memory usage reaches about 400MB before the first getchar (when memory is allocated for 100,000 pages), then it keeps the same even after 99,999 pages are de-allocated (after the second getchar ) and, finally, it drops to 1MB when the last page is de-allocated. 如果您对其进行编译,运行并监视进程的内存使用情况,则可以看到在第一个getchar之前(当内存分配给100,000页时)内存使用量达到了约400MB,然后即使删除了99,999页,它也保持不变。 -allocated(在第二个getchar ),最后,当最后一个页面被取消分配时,它下降到1MB。

So, my question is why is this happening? 所以,我的问题是为什么会这样? Why is the entire memory returned to the OS only when all the pages are freed? 为什么只有释放所有页面后,整个内存才返回给OS? Is there any page size or any page alignment which prevents this sort of thing to happen? 是否有任何页面尺寸或任何页面对齐方式可防止此类情况发生? I mean, is there any page size or alignment the makes any malloced page be entirely returned to the operating system when only one page gets freed? 我的意思是,只有一个页面被释放时,是否有任何页面大小或对齐方式可使任何分配的页面完全返回操作系统?

This is completely implementation-dependent, but I believe that this has to do with how the memory allocator works. 这完全取决于实现,但是我认为这与内存分配器的工作方式有关。 Typically, when the memory manager needs more memory from the OS, it calls the sbrk function to request additional memory. 通常,当内存管理器需要从操作系统获取更多内存时,它将调用sbrk函数以请求更多内存。 The typical implementation of this function is that the OS stores a pointer to the next free address in memory where the process can get space. 此功能的典型实现是OS将指针存储到内存中下一个可用地址的指针,进程可以在其中获得空间。 The memory grows like a stack, much in the same way that the call stack works. 内存就像堆栈一样增长,与调用堆栈的工作方式非常相似。 For example, if you allocated five pages of memory, it might look like this: 例如,如果您分配了五个页面的内存,则可能如下所示:

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

With this setup, if you free pages 0 - 4, the memory manager inside the program will mark them as free, like this: 使用此设置,如果您释放0-4页,则程序内的内存管理器会将其标记为空闲,如下所示:

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

Since the OS is allocating memory in a stack-like fashion, it can't reclaim all this memory from the program until Page 4 is done being used. 由于OS以类似堆栈的方式分配内存,因此在使用完第4页之前,它无法从程序中回收所有这些内存。 Once you free the very last page, the process's memory will look like this: 一旦释放了最后一页,进程的内存将如下所示:

 (existing memory) |                                              (next free spot)

And at this point the program's memory manager can return that huge amount of free space to the OS: 此时,程序的内存管理器可以将大量可用空间返回给操作系统:

 (existing memory) | (next free spot)

In other words, because memory is allocated as a stack, until you deallocate the very last thing you've allocated, the OS can't reclaim any of the memory. 换句话说,由于内存是作为堆栈分配的,因此在取消分配所分配的最后一件事之前,操作系统无法回收任何内存。

Hope this helps! 希望这可以帮助!

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

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