2014-04-15 77 views
2

我添加了一個在我的C++程序代碼中重新啓動的選項。每次重新啓動時,我都可以看到駐留內存增加,而valgrind沒有顯示任何泄漏。什麼可能是居民記憶增加的原因。駐留內存增加,而valgrind沒有顯示任何泄漏

+0

如果您不斷向vector中添加項目,並且在執行結束時清除向量,而這些向量不會在Valgrind中顯示爲泄漏,但並不意味着它不是問題。 – paulm

+0

當你分配一些內存時,系統分配的方式比你提出的要多,通常是頁面大小的倍數,以提高下一次內存分配的性能。由於你的程序沒有結束,系統永遠不會釋放這個內存(釋放程序中的內存只會告訴內存可以再次使用)。 – Chnossos

+0

你究竟「重新啓動」到底如何?這是否涉及殺死它,然後再次啓動該過程? – merlin2011

回答

6

這有幾個可能的原因:

  1. 你可能會越來越多的內存,但實際上沒有泄漏:像vector<int> v; for(;;) v.push_back(1);的事情會在幾秒鐘內耗盡內存,但不是泄漏根據的valgrind 。
  2. 堆是你的「資源」記憶的一部分,所以如果你有一些分配X堆內存的MB,然後將其釋放,除非操作系統實際需要內存用於其他目的,它會留在你的應用程序的一部分記憶。 (實際上,它比這更復雜一點,但對於這個討論,這張圖片是有效的)。
  3. 堆碎片。如果你在堆中分配和釋放內存,並且內存大小變化很大,那麼內存確實是「免費的」,但堆中的塊可能太小而不能用於下一次分配,因此「新鮮」堆被切斷。想象一下,你從一塊長長的木頭開始,將它剪下來以適應某個地方,然後將其取下並再次切割 - 你再也不能將它恢復成全尺寸。 (再次,實際上,這比這更復雜,但對於這個討論來說就足夠了)。

您可能想要使用valgrind的地塊工具,valgrind --tool=massif prog來識別#1等數據隨時間推移而建立的事物。

編輯: 從鏈接的網頁:

地塊是一個堆分析器。它會測量您的 程序使用多少堆內存。這包括有用的空間和分配用於簿記和對齊目的的額外字節 。它也可以測量你的程序堆棧的大小,儘管 默認值沒有這樣做。

mem_heap_extra_B是分配爲「填充」和「開銷」的字節數。它通常只佔總分配大小的一小部分,但如果你有很多非常小的分配,它可以支配堆的使用。

mem_stacks_B是應用程序使用的堆棧的字節數(默認情況下,這不是測量的,因爲它會顯着降低代碼的速度)。

取本程序作爲一個例子:

#include <vector> 

int main(int argc, char **argv) 
{ 
    (void)argv; // Not used. 

    const int size = 10000; 

    std::vector<int*> v(size); 

    switch (argc) 
    { 
    case 1: 
     for(int i = 0; i < size; i++) 
     { 
      v[i] = new int; 
     }; 

     for(int i = 0; i < size; i++) 
     { 
      delete v[i]; 
     }; 
     break; 

    case 2: 
    { 
     int *t = new int [size]; 
     for(int i = 0; i < size; i++) 
     { 
      v[i] = t+i; 
     }; 

     delete [] t; 
     break; 
    } 

    } 

    return 0; 
} 

以下是從valgrind --tool=massif ./a.out(所以case 1:變體的代碼)的輸出端(在高峯使用):

time=2872338 
mem_heap_B=120000 
mem_heap_extra_B=200008 
mem_stacks_B=0 
heap_tree=peak 

其中如果我們與valgrind --tool=massif ./a.out 1(所以case 2: criant代碼的)運行時,在高峯使用時,輸出的是:

time=2523909 
mem_heap_B=120000 
mem_heap_extra_B=16 
mem_stacks_B=0 
heap_tree=peak 

請注意mem_heap_extra_B在第一種情況下的差異是多大於實際的堆使用量(因爲每4個字節的分配實際上佔用了很多),在第二種情況下,額外的字節只有16個,但堆的實際「已用」大小是相同的,120000(這是有道理的,我們有8個字節10000個指針,每個4個字節+ 10000個整數)。

不幸的是,這個程序是相當無趣,當談到疊加使用,但如果你使用--stacks=yes,它會顯示使用的堆棧的字節數,如:

time=2222719 
mem_heap_B=120000 
mem_heap_extra_B=16 
mem_stacks_B=528 

如果我在grep命令查找mem_stacks_B在Pascal編譯器我的工作,那麼它變得更有趣:

10:mem_stacks_B=0 
18:mem_stacks_B=1576 
26:mem_stacks_B=1368 
34:mem_stacks_B=1368 
42:mem_stacks_B=1576 
50:mem_stacks_B=120 
58:mem_stacks_B=2592 
66:mem_stacks_B=4656 
288:mem_stacks_B=2464 
296:mem_stacks_B=43104 
431:mem_stacks_B=2424 
439:mem_stacks_B=10960 
447:mem_stacks_B=8096 
622:mem_stacks_B=8352 
887:mem_stacks_B=3816 
895:mem_stacks_B=3360 
903:mem_stacks_B=3664 
911:mem_stacks_B=3216 

有很多多,但足以說明「堆棧使用變化頗有幾分」。

正如你所看到的,它變化很大。不,我沒有試圖弄清楚它在使用43KB堆棧時的作用 - 反正它並不是真正的無用。

+0

感謝@Mats,我用地塊來識別這些問題,但我無法理解out文件。我瀏覽並找到了一些關於它的信息,但我仍不清楚mem_heap_extra_B和mem_stacks_B的意義。正如我的理解mem_heap_extra_B是我的編程沒有使用的額外堆內存,因此這可能是增加Resident大小的原因。如果這是一個原因,我該如何擺脫它..? – piyush

+0

繼續... plz糾正我,如果我錯了,請也解釋我關於mem_stacks_B。 – piyush