2013-03-30 56 views
0

無法找出發生了什麼問題。使用大量的unique_ptr後釋放內存到os - C++

下面是一個簡單的代碼

size_t n_elem = 30000000; //careful! will allocate 1GB with unique_ptr 
vector<unique_ptr<double> > tmp; 
tmp.resize(n_elem); 
for(size_t i=0; i<n_elem; i++){ 
    tmp[i] = unique_ptr<double>(new double((double)i)); 
} 
tmp.clear(); 
//Some answers in Stack overflow seems to suggest this technique to force 
//freeing, but does not seem to work. 
vector<unique_ptr<double> > tmp1; 
tmp.swap(tmp1); 

當此完成。當系統監視器顯示內存使用率高峯時,系統監視器仍然顯示948 MB的分配情況,然後將所有內容都釋放正確。即使該代碼段被括在括號{...}中以確保範圍,但我沒有看到任何改進。內存分配後,它似乎不會釋放,直到程序結束。

懷疑與矢量的東西,我嘗試了下面的代碼,但具有相同的行爲。

{ 
    size_t n_elem = 30000000; 
    unique_ptr<double>* tmp = new unique_ptr<double>[n_elem]; 
    for(size_t i=0; i<n_elem; i++) 
     tmp[i] = unique_ptr<double>(new double((double)i)); 
    delete[] tmp; 
} 

然而,

size_t n_elem = 30000000; 
double *d_tmp; 
d_tmp = new double[n_elem]; 
for(size_t i=0; i<n_elem; i++) 
{ 
    d_tmp[i] = (double)i; 
} 
delete[] d_tmp; 

此代碼顯示的存儲器使用量上升至約260 MB和作爲陣列被刪除,則減小。

我試着用類而不是double來計算析構函數被靜態變量調用的次數。在這兩種情況下,析構函數被稱爲正確的次數。

我無法弄清楚我使用unique_ptr的方式有什麼問題,以及爲什麼在銷燬後沒有返回分配給操作系統的內存。 cpp參考似乎暗示這會在uniue_ptrs被破壞時自動發生。我如何讓unique_ptr釋放已分配的內存並將其返回給操作系統?

這發生在gcc 4.6與Ubuntu 12.04和qtcreator qt項目。

+0

您正在創建兩個unique_ptr數組,並且只刪除一個? – yngccc

+0

@yngum,不,即使在第二個代碼片段中也會出現問題。片段獨立運行。第一個片段用當前向量交換一個空向量。 – sri

+0

第二個片段還會爲每個元素創建兩個unique_ptr – yngccc

回答

0

稍微改變你的代碼

tmp.clear(); // it is not needed 
{ 
    //Some answers in Stack overflow seems to suggest this technique to force 
    //freeing, but does not seem to work. 
    vector<unique_ptr<double> > tmp1; 
    tmp.swap(tmp1); 
} 
// measure memory here 
+0

謝謝,但似乎沒有工作。我看到相同的內存使用。 – sri

0

嘗試改變這一點:

tmp[i] = unique_ptr<double>(new double((double)i)); 

要:

tmp[i].reset(new double((double)i)); 

而且,我不敢知道你打算什麼做(或者更好地瞭解),但是如果你想要複製的是一個動態分配的雙數組,你不需要把它保存起來unique_ptr的。請直接使用vector<double>。否則,您要爲要存儲的每個double創建一個unique_ptr。這是而不是與連續分配的數組相同(從而利用局部性/高速緩存)。這似乎招致不必要的開銷。

+0

謝謝。但是,這似乎也不能解決問題。這只是一個孤立的案例。唯一的指針實際上是在一個類中用於基於樹的表示,其中可能有一些未知數的子元素。我使用unique_ptr在對象被銷燬時不用擔心清理,但我注意到內存永遠不會下降。我懷疑該類中的代碼,但事實證明,我能夠在這些代碼片段中複製相同的行爲。 – sri

+0

@sri您真的在使用您提供的示例代碼進行檢查嗎?或者你在測試中使用'unique_ptr '而不是?我只是通過valgrind運行它,它說沒有內存泄漏。作爲一個方面說明,在迴應你的評論時,我並不是說要詛咒這件事,但似乎你應該可以在班上使用'vector children'。我認爲那裏不需要'unique_ptrs'。 –

+0

我正在檢查問題中的示例代碼。我也檢查了沒有內存泄漏,但是,它似乎沒有釋放內存到操作系統,直到程序退出後,這可能是麻煩的。我會嘗試矢量的想法,看看它是如何發展的。 – sri

0

通常情況下,內存管理器在需要時向操作系統請求更多的內存,但在完成後不要嘗試將其還給操作系統。後者通常很難做到,因爲堆使用會趨於飛濺,而且知道何時不再需要操作系統大小的內存塊時會涉及太多的簿記。此外,即使內存管理器這樣做,操作系統可能會將該內存分配給您的程序,直到在其他地方需要它,因此報告內存使用情況的操作系統工具不會反映您的應用程序實際使用的內容。

這裏真正的問題是這個多餘的內存是否會產生問題;通常OS通過交換到磁盤來管理大型工作集;未使用的內存塊會佔用後臺存儲空間,但不會佔用內存。