2011-11-18 153 views
3

我有一個非常簡單的問題,我似乎被困在發生的事情。請看下面的代碼:CArray沒有取消分配內存

CArray<double, double&> arr; 
arr.SetSize(50000); 

for(int i =0; i< 50000; i++) 
{ 
    arr[i] = (i+2)*3.14f; 
} 

arr.RemoveAll(); 

我會假設,RemoveAll()後,內存將被釋放,但現在看來似乎沒有發生。要檢查內存佔用情況,請打開Taskmanager並觀察exe的內存。它在arr.SetSize()呼叫上增加,但即使此arr超出範圍,它也不會減少。有人可以對此進行闡述嗎?

回答

7

第一件事:

任務管理器=內存分析器

操作系統(或者更具體地說是C運行時系統)肯定會緩存一些你分配的內存。

注意,操作系統通常不是啞巴 - 如果它是不是正在使用的應用程序的內存和操作系統需要更多的內存來滿足其他一些程序的內存需求,這將相應地分配。但是,如果情況並非如此(大多數情況下不是這樣),那麼當應用程序成爲獲勝策略時,應該重複使用它。

由於這些類型的優化,你真的不能使用任務管理器獲取應用程序的內存使用情況的精確視圖。

第二件事:

像所有非傻動態數組類,CArray當你刪除所有的情況下,你需要再次使用的內存緩衝區中的元素不會釋放內存甚至支持的陣列。如果刪除底層內存緩衝區只會浪費更多的處理器週期來重新分配另一個緩衝區來處理可能在CArray::RemoveAll()之後發生的下一個CArray::Append()調用,那麼這會浪費處理器週期。

如果你真的想擺脫多餘的空間,使用CArray::FreeExtra()。請注意,該函數可能涉及分配一個新的緩衝區並將這些元素複製到新的緩衝區,然後刪除舊的緩衝區。

+0

我試過FreeExtra,但它仍然無法正常工作。我知道任務管理器不是內存分析器,但這是最容易獲得的東西。還有其他建議嗎? – Aamir

+0

@In Silico,爲什麼FreeExtra需要分配一個新的緩衝區來減小大小?當然,如果它使用realloc來縮小所使用的內存量,最終會產生碎片堆,那麼可以避免額外堆空間的內存開銷以及複製和調用ctors和dtors的時間開銷。 –

+0

@Shane MacLaughlin:這是一種可行的方法。但是,文檔沒有具體說明也沒有做出任何保證,讓它像那樣工作(我已經重寫了這句話)。它不是普遍的;例如'std :: vector'幾乎肯定會分配一個新緩衝區並刪除舊緩衝區,因爲分配器接口沒有'realloc()'能力。 –

1

你需要調用FreeExtra您的removeAll後獲取內存了。我猜這是爲了避免堆碎片。

2

正如別人所說,removeall過不會釋放CARRAY分配的內存,你需要調用CARRAY :: FreeExtra。

你說在CArray的析構函數之後內存不會下降。 CArray :: SetSize從堆中分配內存,CArray的析構函數釋放它。但是,這並不意味着堆內存將回饋給操作系統。

當您使用MFC我建議不時在調試器中啓動程序。 MFC調試應用程序在MFC清理過程中打印出他們的內存泄漏(基於新的)。