2011-09-22 29 views
5

在我簡單的C程序(gnu linux)中,我得到了proc/stat的rss值。
int GetRSS()從我的過程返回proc/stat的RSS值。瘋狂是免費的()


在這種情況下:

printf("A RSS=%i\n", GetRSS()); 
char *cStr = null; 
cStr = malloc(999999); 
if (cStr != NULL) 
{ 
    printf("B RSS=%i\n", GetRSS()); 
    free(cStr); 
    printf("C RSS=%i\n", GetRSS()); 
} 

我得到:

A RSS=980 
B RSS=984 
C RSS=980 

我無法解釋爲什麼C沒有返回984


如果我運行同樣的程序我兩次獲得:

A RSS=980 
B RSS=984 
C RSS=980 
B RSS=984 
C RSS=980 

看起來不錯。


但是,在這種情況下:

struct _test 
{ 
    char *pChar; 
} 
struct _test **test_ptr; 

int i = 0; 
printf("D RSS=%i\n",GetRSS()); 
assert(test_ptr = (struct _test **)malloc((10000) * sizeof(struct _test *))); 

for (i = 0; i < 1000; i++) 
{ 
    assert(test_ptr[i] = (struct _test *)malloc(sizeof(struct _test))); 
    test_ptr[i]->pChar=strdup("Some garbage"); 
} 

printf("E RSS=%i\n", GetRSS()); 

for (i=0; i<1000; i++) 
{ 
    free(test_ptr[i]->pChar); 
    free(test_ptr[i]); 
} 

free(test_ptr); 
printf("F RSS=%i\n", GetRSS()); 

我得到:

D RSS=980 
E RSS=1024 
F RSS=1024 
D RSS=1024 
E RSS=1024 
F RSS=1024 

咦?爲什麼記憶不在這裏釋放?

+9

您不應該將帶有副作用的表達式放入'assert'中。 –

+0

確實夠了。忽略它。但結果卻令人困惑。 –

+1

在「strace」下運行您的程序,以便您可以監視實際上會對RSS值產生影響的mmap/munmap調用。您可以在代碼中放置一些printfs,以便您可以將mmap/munmap與輸出中代碼的特定點進行匹配。 – vanza

回答

5

一塊內存已被釋放的事實而不是必然使該塊最適合後續分配。內存管理器有幾種選擇內存塊的策略(最佳擬合,最差擬合,首次擬合)。

大多數內存管理器也會嘗試合併空閒塊,但有些嘗試在合併之前儘可能長時間讓空閒塊「老化」,理論上說,隨着它們的老化,它們旁邊的塊會有更好的機會也可以被釋放,提高合併塊的成功率(從而減少碎片化)。

該塊未用於滿足您的下一個分配請求的事實而不是表示它沒有被釋放。

1

您的malloc庫選擇不這樣做。這可能是出於戰略原因(避免以後必須去系統獲得更多內存),或者可能是由於限制(在該特定原因下,它不認識到它可以釋放內存)。

一般來說,沒關係。地址空間和虛擬內存通常不被視爲稀缺資源。因此,儘量減少消費量通常是毫無價值的,而且往往是有害的。

2

free()手冊頁:「偶爾,free可以實際將內存返回給操作系統,並且使進程變得更小。通常情況下,只需稍後再調用malloc即可重用該空間。同時,該空間作爲malloc內部使用的自由列表的一部分保留在程序中。「

+0

在產生這個問題的真正程序的情況下,它最終會耗盡內存並崩潰。我的測試表明分配給該結構的內存不會被釋放。此外,strace不會顯示與malloc相關的mmap2或munmap調用,也不會顯示結構(及其char *)。我仍然難倒。 –

+0

@MarkRichards:我剛剛在WinDbg中介紹了您的程序(現在沒有可用的Linux機器),用'!heap'檢查提交的內存。它工作正常。似乎沒有任何內存泄漏。請記住,glibc的'malloc'和'free'不需要調用mmap/munmap,因爲已經爲CRT堆保留了未編譯的內存。你什麼意思最終耗盡內存和崩潰?你也許可以將你的整個程序貼上去? –

+0

非常有趣。我會在另一個(不同的)盒子上做同樣的事情。我修改了程序 - 刪除了第一個工作的malloc。仍然無法調用mmap。請參閱:http://pastebin.com/m3gAJBhs –