2015-09-05 26 views
1

一些測試用任務管理器的幫助後,我明白了一件事gcnew - 分配給本地變量remaines分配,即使在控制離開功能,並且只重新分配內存時控制再次進入該功能 - 所以我在困惑,如何自己釋放記憶。這是問題的一些例子:如何釋放由gcnew分配的內存?

void Foo(void) 
{ 
    System::Text::StringBuilder^t = gcnew System::Text::StringBuilder(""); 
    int i = 0; 
    while(++i < 20000000) t->Append(i); 
    return; 
} 

正如我所說,內存變量t仍然留下Foo()delete無法正常工作,它爲new,並呼籲Foo()一次後,只給了我毫無意義分配的內存。

+1

爲什麼你首先動態分配它? – emlai

+1

爲什麼你最初使用託管C++?這就像吃沒有糖的蛋糕。 –

+0

分配給垃圾收集系統的進程的內存僅受其性能和良好的公民目標的限制。你應該期望它不會不必要地填滿你的硬盤。 –

回答

0

這是gcnew,這意味着垃圾收集分配。它將通過GC線程進行處理和釋放。

0

您的函數使用內存代碼和數據。該代碼是一個固定的數量,將在整個庫或程序加載時使用。數據僅在函數執行時使用。

程序使用的數據是靜態或動態的。靜態數據由編譯器進行佈局,基本上等同於代碼(除了它可能被標記爲不可執行和/或只讀以防止事故)。動態數據是臨時的,並且從堆棧或堆(或CPU寄存器)分配。

在一個經典程序,棧和堆共享相同的存儲器地址範圍與所述疊層的一端,朝向所述堆和在另一端的堆生長,儘量不成長爲堆棧。但是,現代地址範圍大約爲1TB,堆通常有很大的空間。

請記住,當程序請求一個地址範圍,它只是信號的操作系統,它沒關係使用該地址進行數據讀取,數據寫入和/或執行代碼。在它實際上放置了某些東西之前,系統上沒有任何負載。還要記住虛擬內存系統,在交換文件/設備(硬盤驅動器)上有效分配進程內存,並進行優化,尤其是使用RAM進行緩存,寫入時複製以及許多其他技術。 (寫入存儲器地址的數據可能永遠不會進入交換文件,但這是高達操作系統。)


您的功能需要的數據是兩個變量:tit是對垃圾收集對象的引用。 i是一個整數。兩者都很小而且壽命短。你可以認爲他們在堆棧中。當函數返回時,堆棧框架將彈出,並且它們的內存將被下一個堆棧操作重用。如果您正在查看內存分配情況,則不會有任何變化,因爲分配給堆棧的內存量不會改變。

現在在你的函數的執行,創建一個新的對象,然後,它充滿了數據的方式,它佔用了不少的內存。您可以考慮在堆中創建該對象。你不需要刪除它,因爲它是一個垃圾收集對象。當垃圾收集器通過遍歷一組根對象可訪問的所有對象來運行時,它會發現該對象無法訪問並將其空間添加到空閒列表中。當需要一個不適合空閒列表中的任何塊的新對象空間時,將使用更多堆的地址範圍。

CLR堆是可壓縮的,這意味着它可以移動物體以合併空閒塊。使用此功能,它可以將對象移出分配的內存區域並將其返回給操作系統,從而釋放交換文件中的空間。

因此,有要發生給你看在分配給進程的內存量減少三兩件事:

  1. 垃圾收集已運行發現不可達的對象。
  2. 堆已壓縮。
  3. 堆分配已減少。

直到交換文件無法再增長,這些東西才真正需要。顯然,這個系統是爲了表現而設計的,並且是一個好公民,所以它不會那麼做。您可以影響垃圾回收的運行時間,但這只是非常有用的,通常不會完成。