2011-08-24 75 views
2

我有以下代碼:C程序的內存使用 - 更多的內存報道比分配

int main() 
{ 
    char * str1 = (char*)malloc(101 * sizeof(char)); 
    for (int i=0; i<100; i++) 
    { 
     str1[i] = 'b'; 
    } 
    str1[100] = 0; 

    char * str2 = (char*)malloc(1001 * sizeof(char)); 
    for (int i=0; i<1000; i++) 
    { 
     str2[i] = 'a'; 
    } 
    str2[1000] = 0; 


    for (int i=0; i<7000; i++) 
    { 
     char * tmp = str2; 
     str2 = (char*) malloc((strlen(str2) + strlen(str1) + 1) * sizeof(char)); 
     sprintf(str2, "%s%s", tmp, str1); 
     free(tmp); 
    } 

    free(str1); 
    free(str2); 
} 

當運行它,任務管理器報告如下內存使用: 年初計劃 - 1056K,的 結束程序 - 17,748K

據我所知沒有內存泄漏,我編譯它沒有調試符號(發佈模式)。

任何想法爲什麼會發生這種情況?

+0

您是否使用內存調試器檢查過內存是否實際泄露? –

+0

這可能會幫助您http://www.cprogramming.com/debugging/valgrind.html – nu6A

回答

10

我認爲這是因爲free不必將內存返回到操作系統。它只是將它返回到免費池,從中可以分配到malloc

+1

當您分配的內存超過操作系統爲您的程序指定的內存量時,操作系統會增加可供您的程序使用的內存量。釋放內存時,可用的數量不一定會減少。 – mydogisbox

+0

是的,此行爲完全由在任何給定主機上實施VMM來定義。所有'free()'都表示內存不再需要。這是爲什麼在懸掛指針上操作導致未定義行爲的原因之一。 –

+0

嗯,這似乎符合我在調試過程中注意到的行爲......每次我調用malloc時,mem的使用情況都不會增加,但會不時增加。 – mihai

3

這可能是malloc從可用的內存池中選擇以滿足malloc的人爲因素。另外,TaskManager和top(對於unix)等工具在提供進程使用的實際內存指示方面非常糟糕。每當我的一個客戶給我一個最高的輸出並告訴我我的過程正在泄漏時,我就會畏縮,因爲現在我必須證明它不是。

+1

準確。任務管理器的輸出非常不可靠。 –

1

malloc是C標準庫提供的內存管理功能。當你的程序調用malloc時,它不直接從操作系統分配內存。 Malloc實現通常具有一個內存池,它們分割成塊來滿足分配請求。當你打電話給你時,你只會把你的記憶塊放回這個記憶庫。

對malloc的重複調用最終會從標準庫管理的內存池中分配所有內存。此時需要進行系統調用以從操作系統獲得更多內存。在linux上,這是brk系統調用,毫無疑問,這在Windows上是類似的。

任務管理器在Windows,或頂部在Linux中,將報告操作系統已分配給你的進程的內存量。這通常會超過程序通過malloc分配的內存量。

如果ltrace程序在Linux上,你可以看到正在進行的

ltrace -S <some program> 
malloc(65536 <unfinished ...> 
SYS_brk(NULL)    = 0x2584000 
SYS_brk(0x25b5000)   = 0x25b5000 
SYS_brk(NULL)    = 0x25b5000 
<... malloc resumed>)  = 0x2584010 

在這個例子中,我們嘗試的malloc(65536)這些malloc和BRK電話,但malloc的系統沒有足夠的可用內存來滿足這個要求。所以它調用了brk()系統調用來從操作系統獲得更多內存。這個調用完成後,它可以恢復malloc調用併爲程序提供它所請求的內存。