簡體   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