看記憶體是否有泄漏的時候,最簡單的方法是查看Task Manager
實體記憶體和虛擬記憶體
要理解記憶體在程式中是如何分配的,首先需要理解如何將記憶體從作業系統分配給程式。電腦上的每一個進程都認為自己可以訪問所有的實體記憶體。顯然,由於同時在運行多個程式,所以每個進程不可能擁有全部記憶體。實際上,這些進程使用的是
虛擬記憶體。
只是作為一個例子,讓我們假定您的程式正在訪問地址為 629 的記憶體。不過,虛擬記憶體系統不需要將其儲存在位置為 629 的 RAM (隨機存取儲存空間)中。實際上,它甚至可以不在 RAM 中 —— 如果物理 RAM 已經滿了,它甚至可能已經被轉移到硬碟上!由於這類地址不必反映記憶體所在的物理位置,所以它們被稱為虛擬記憶體。作業系統維持著一個虛擬位址到物理地址的轉換的表,以便電腦硬體可以正確地響應地址請求。並且,如果地址在硬碟上而不是在 RAM 中,那麼作業系統將暫時停止您的進程,將其他記憶體轉存到硬碟中,從硬碟上載入被請求的記憶體,然後再重新啟動您的進程。這樣,每個進程都獲得了自己可以使用的地址空間,可以訪問比您物理上安裝的記憶體更多的記憶體。
在 32-位 x86 系統上,每一個進程可以訪問 4 GB 記憶體。現在,大部分人的系統上並沒有 4 GB 記憶體,即使您將 swap 也算上, 每個進程
所使用的記憶體也肯定少於 4 GB。因此,當載入一個進程時,它會得到一個取決於某個稱為 系統中斷點(system break)的特定地址的初始記憶體配置。該地址之後是未被映射的記憶體 —— 用於在 RAM 或者硬碟中沒有分配相應物理位置的記憶體。因此,如果一個進程運行超出了它初始分配的記憶體,那麼它必須請求作業系統“映射進來(map in)”更多的記憶體。(映射是一個表示一一對應關係的數學術語 —— 當記憶體的虛擬位址有一個對應的物理地址來儲存記憶體內容時,該記憶體將被映射。)
在多任務環境下,所有進程使用的記憶體總和可以超過電腦的實體記憶體。在特定的情況下,進程的一部分可能會從實體記憶體中刪除而被暫存在硬碟的檔案裡(page file),當進程試圖訪問這些被交換到硬碟的檔案裡的記憶體的時候,系統會產生一個缺頁中斷(page fault),這時候Windows記憶體管理器會負責把對應的記憶體頁重新從硬碟調入實體記憶體。
在某個時間內,一個進程可以直接存取到的實體記憶體(不發生缺頁中斷)叫做這個進程的 Working Set ;而一個進程從4G的地址空間當中實際分配(commit)了的、可訪問的記憶體稱為 Committed Virtual Memory 。Committed VM可能存在於Page File當中,Working Set則一定位於實體記憶體。
Mem Usage這個名字多少有些誤導。它只表示這個進程當前佔用的實體記憶體,也就是Working Set。Working Set不表示進程當前“佔用”的所有虛擬記憶體,該進程可能還有一部分資料被交換到page file當中。這些資料只有在被訪問的時候才會被載入到實體記憶體。
Task Manager有另一列資料:VM Size,表示了一個進程分配的虛存(Committed Visual Memory)
所以,結論很簡單: 當一個Windows程式被最小化的時候,Windows記憶體管理器把該進程的Working Set減到最小(根據先進先出FIFO或者最近最少使用LRU),把大部分資料交換到page file裡。 這很容易理解:我們通常總是希望為前台的應用程式留出更多實體記憶體,從而具有更好的效能。 當該程式從最小化恢複的時候,Windows也不會完全載入程式的所有虛存,只是載入了必要的部分。 這也很容易理解:程式啟動階段的代碼通常在啟動之後很少訪問