HeapAlloc和GlobalAlloc以及VirtualAlloc三者之間的關係

VirtualAlloc一次分配1PAGE以上的RAM. 每次分配都是PAGE的整數倍. 你不會想爲了分配1個BYTE的空間而浪費剩下的4095字節. OK. 你可以自己寫算法,多分 配幾PAGE. 然後每次分配少量數據時就從那幾PAGE中劃分出來. 什麼? 你笨到不會寫分 配算法? 好巴 KERNEL32給你一個解決辦法. 用HeapAlloc/GlobalAlloc分配RAM. 這樣, KERNEL32幫你完成分配動作, 並且儘量在減少用於跟蹤空閒區域和已佔用區域消耗的數 據結構.       很久以前也有個產品叫做WINDOWS. 那時候的WINDOWS是16BIT的. 地址空間有些緊俏. 有錢不夠. 還需要糧票肉票才能拿到. 你已經調用GlobalAlloc和已經出錢的性質一樣. GlobalAlloc還不夠. 有時候需要GlocalLock才能確定你的東西確實可以拿到手.不然你 的指針會非法. 被充公. 你的應用會被殺頭. 扯遠了. 後來OS進化了. 覺得可以取消糧 票肉票. 但是你必須用新版鈔票才行. 那就是HeapAlloc. 只要市場上的RAM數量沒問題 . 你的HeapAlloc沒問題. 那就總能拿到東西. 但是, 你總不能說有了2000版的鈔票, 那80版的馬上作廢啊. 那GlobalAlloc也只好繼續流通下去. 至於可以流通到什麼時候. 沒人知道.

 

GlobalAlloc和LocalAlloc都是Windows系統提供的內存分配函數,他們的區別源於16位代碼時代,那時沒有不同的進程內存 空間,GlobalAlloc是在全局的、公用的遠堆上分配,LocalAlloc則在任務自己的近堆上分配。在Win32平臺下這兩個函數是完全相同 的,都是在進程自己的內存空間中分配,Lock之後的結果是普通指針(32位近指針)。           new與它們的區別未免太大,因爲與C++的構造函數和異常機制有關。一般編譯器中的new都是用malloc來分配內存的。用malloc與其它兩 個函數比較應該更合理。一般malloc的實現並不是從系統的堆中分配的,而是從編譯器連接的運行庫自己管理的堆中,在Win32平臺上的開發工具的編譯 結果中,通常是用HeapCreate創建一個堆,用HeapAlloc和HeapRealloc維護堆的空間增長,在最後用HeapDestroy刪除 堆。而在用malloc分配、用free釋放時則由運行庫的代碼負責從這個堆中分配空間和向這個堆中歸還空間,並維護這個堆中的數據結構。           由於malloc堆的管理是由運行庫自己管理的,所在當我們使用靜態運行庫時,如果在一個DLL中用malloc分配了內存而在另一個DLL中用 free去釋放它,通常都會產生問題,這是因爲每個DLL都連接了一份運行庫的代碼,從而也都有一個自己的局部堆,而在用free釋放時它會假設這塊內存 是在自己的堆中分配的,從而導致錯誤。而通過GlobalAlloc和LocalAlloc分配的內存不存在這個問題。

 

HeapCreate就已經完成了創建堆的操作,HeapAlloc、HeapRealloc和HeapFree都是從這個堆中分配、釋放內存的函 數。也就是說,Windows系統其實已經爲我們提供了完整的一套使用自己的局部堆的操作,不過沒有看到指定分配策略的方法。根據編譯器提供的源代碼來 看,VC中的malloc、realloc和free等函數主要功能就是用這幾個API函數來實現的,而BC中的實現相當複雜,似乎是維護了一套自己的邏 輯。據說BC的內存分配比VC快,大概就是這個原因了。

 

發佈了0 篇原創文章 · 獲贊 4 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章