2010-12-21 55 views
5

我使用SysInternals的VMMap來查看WinXP上我的Win32 C++進程分配的內存,並且我看到一堆分配,其中分配內存的一部分被保留但未提交。據我所知,從我的閱讀和測試中,在C++程序中使用的所有常見內存分配器(例如,malloc,new,LocalAlloc,GlobalAlloc)總是分配完全承諾的內存塊。 堆是代碼的一個常見示例,它保留內存但在需要之前不提交它。我懷疑其中一些塊是Windows/CRT堆,但似乎有更多的這些類型的塊比我預期的堆。在我的過程中,我看到這些塊中有30個塊的大小在64k到8MB之間,我知道我的代碼從不故意調用VirtualAlloc來分配保留的,未提交的內存。我的過程中所有這些未提交的保留內存是什麼?

這裏有幾個例子,從的VMMap:http://www.flickr.com/photos/[email protected]/5280550393/

什麼人會分配內存這樣的塊,其中它更是保留但未提交?我的過程有30堆是否合理?謝謝。

+0

我不認爲在一次兩個地方發佈完全相同的問題並不是很好。 http://forum.sysinternals.com/uncommitted-reserved-memory-in-my-process_topic24690.html – wj32 2010-12-21 21:29:10

+8

我認爲這很好。 Sysinternals是VMMap工具的作者,因此他們可能知道他們的工具爲什麼要報告這些信息。 StackOverflow上的人們可能知道哪些代碼會以這種模式分配內存。兩個不同的受衆可能不會閱讀這兩個論壇。 – Art 2011-01-04 19:18:59

回答

7

我想通了 - 它是通過調用malloc分配的CRT堆。如果使用malloc分配一大塊內存(例如,2 MB),它將分配一個確定的內存塊。但是,如果你分配較小的塊(比如說177kb),那麼它將保留1MB的內存塊,但只能提交大約你所要求的內容(例如,對於我的177kb請求,這是184kb)。當釋放該小塊時,較大的1 MB塊不會返回到操作系統。除4k以外的所有內容均未提交,但完整的1 MB仍保留。如果您再次調用malloc,它將嘗試使用該1 MB塊來滿足您的請求。如果它不能滿足你的請求,而它的內存已經被保留了,它將分配一個新的內存塊,這是以前分配的兩倍(在我的情況下,它從1 MB變爲2 MB)。我不確定這種加倍模式是否繼續。要真正將釋放的內存返回到操作系統,您可以調用heapmin。我認爲這會使未來的大分配更有可能獲得成功,但是這將全部取決於內存碎片,並且如果分配失敗(?),heapmin可能已被調用,但我不確定。由於heapmin會釋放內存(需要花費時間),並且malloc隨後需要在需要時重新從操作系統重新分配,所以也會有性能問題。此信息適用於Windows/32 XP,您的里程可能會有所不同。

更新:在我的測試中,heapmin沒有做任何事情。 malloc堆只用於小於512kb的塊。即使malloc堆中有連續可用空間的MB,它也不會用於超過512kb的請求。在我的情況下,這個被釋放,未使用但保留的malloc內存咀嚼了我的進程的大部分2GB地址空間,最終導致內存分配失敗。而且由於heapmin不會將內存返回到操作系統,除了重新啓動我的進程或編寫我自己的內存管理器外,我還沒有找到任何解決此問題的方法。

0

他們可能是加載到您的過程中的DLL? DLL(和可執行文件)被內存映射到進程地址空間。我相信這最初只是預留空間。該空間由文件本身(至少在最初)而不是頁面文件支持。

只有真正觸摸的代碼纔會被分頁。如果我正確理解術語,那就是它的提交時間。

您可以通過在調試器中運行您的應用程序並查看加載的模塊並將它們的位置和大小與您在VMMap中看到的內容進行比較來確認此情況。

0

每當在應用程序中創建一個線程時,線程調用堆棧的地址空間中將保留一定的(可配置的)內存量。除非你的線程真的需要所有的內存,否則不需要提交所有保留的內存。所以只有一部分需要承諾。

如果需要超過承諾量的內存,將有可能獲得更多的系統內存。

實際的考慮是保留內存是堆棧大小的硬限制,這會減少應用程序可用的地址空間。但是,只需提交一部分備用數據,我們就不必從系統中消耗相同數量的內存直到需要爲止。

因此,每個線程都可能有一部分保留的未提交內存。我不確定在這些情況下的頁面類型。

相關問題