HeapAlloc,GlobalAlloc,LocalAlloc,VirtualAlloc,malloc,new的異同
1. 首先我們來看HeapAlloc:MSDN上的解釋為:HeapALloc是從堆上分配一塊內存,且分配的內存是不可移動的(即如果沒有連續的空間能滿足分配的大小,程序不能將其他零散的 空間利用起來,從而導致分配失敗),該分配方法是從一指定地址開始分配,而不像GloabalAlloc是從全局堆上分配,這個有可能是全局,也有可能是 局部。函數原型為:
LPVOID
HeapAlloc(
HANDLE hHeap,
DWORD dwFlags,
SIZE_T dwBytes
);
hHeap是進程堆內存開始位置。
dwFlags是分配堆內存的標誌。包括HEAP_ZERO_MEMORY,即使分配的空間清零。
dwBytes是分配堆內存的大小。
其對應的釋放空間函數為HeapFree。
2. 再看GlobalAlloc:該函數用於從全局堆中分配出內存供程序使用,函數原型為:
HGLOBAL GlobalAlloc(
UINT uFlags,
SIZE_T dwBytes
);
uFlags參數含義
GHND GMEM_MOVEABLE和GMEM_ZEROINIT的組合
GMEM_FIXED 分配固定內存,返回值是一個指針
GMEM_MOVEABLE 分配活動內存,在Win32中,內存塊不能在物理內存中移動,但能在默認的堆中移動。返回值是內存對象的句柄,用函數GlobalLock可將句柄轉化為指針
GMEM_ZEROINIT 將內存內容初始化為零
GPTR GMEM_FIXED和GMEM_ZEROINIT的組合
一般情況下我們在編程的時候,給應用程序分配的內存都是可以移動的或者是可以丟棄的,這樣能使有限的內存資源充分利用,所以,在某一個時候我們分配的那塊 內存的地址是不確定的,因為他是可以移動的,所以得先鎖定那塊內存塊,這兒應用程序需要調用API函數GlobalLock函數來鎖定句柄。如下: lpMem=GlobalLock(hMem); 這樣應用程序才能存取這塊內存。所以我們在使用GlobalAllock時,通常搭配使用GlobalLock,當然在不使用內存時,一定記得使用 GlobalUnlock,否則被鎖定的內存塊一直不能被其他變量使用。
GlobalAlloc對應的釋放空間的函數為GlobalFree。
3. LocalAlloc:該函數用於從局部堆中分配內存供程序使用,函數原型為:
HLOCAL LocalAlloc(
UINT uFlags,
SIZE_T uBytes
);
參數同GlobalAlloc。
在16位Windows中是有區別的,因為在16位windows用一個全局堆和局部堆來管理內存,每一個應用程序或dll裝入內存時,代碼段被裝入全局 堆,而係統又為每個實例從全局堆中分配了一個64kb的數據段作為該實例的局部堆,用來存放應用程序的堆棧和所有全局或靜態變量。而 LocalAlloc/GlobalAlloc就是分別用於在局部堆或全局堆中分配內存。
由於每個進程的局部堆很小,所以在局部堆中分配內存會受到空間的限製。但這個堆是每個進程私有的,相對而言分配數據較安全,數據訪問出錯不至於影響到整個係統。
而在全局堆中分配的內存是為各個進程共享的,每個進程隻要擁有這個內存塊的句柄都可以訪問這塊內存,但是每個全局內存空間需要額外的內存開銷,造成分配浪費。而且一旦發生嚴重錯誤,可能會影響到整個係統的穩定。
不過在Win32中,每個進程都隻擁有一個省缺的私有堆,它隻能被當前進程訪問。應用程序也不可能直接訪問係統內存。所以在Win32中全局堆和局部堆都 指向進程的省缺堆。用LocalAlloc/GlobalAlloc分配內存沒有任何區別。甚至LocalAlloc分配的內存可以被 GlobalFree釋放掉。所以在Win32下編程,無需注意Local和Global的區別,一般的內存分配都等效於 HeapAlloc(GetProcessHeap(),...)。
LocalAlloc對應的釋放函數為LockFree。
4. VirtualAlloc:該函數的功能是在調用進程的虛地址空間,預定或者提交一部分頁,如果用於內存分配的話,並且分配類型未指定MEM_RESET,則係統將自動設置為0;其函數原型:
LPVOID VirtualAlloc(
LPVOID lpAddress, // region to reserve or commit
SIZE_T dwSize, // size of region
DWORD flAllocationType, // type of allocation
DWORD flProtect // type of access protection
);
VirtualAlloc可以通過並行多次調用提交一個區域的部分或全部來保留一個大的內存區域。多重調用提交同一塊區域不會引起失敗。這使得一個應用程 序保留內存後可以隨意提交將被寫的頁。當這種方式不在有效的時候,它會釋放應用程序通過檢測被保留頁的狀態看它是否在提交調用之前已經被提交。
VirtualAlloc對應的釋放函數為VirtualFree。
5.Malloc:malloc與free是C++/C語言的標準庫函數,可用於申請動態內存和釋放內存。對於非內部數據類型的對象而言,光用 malloc/free無法滿足動態對象的要求。對象在創建的同時要自動執行構造函數,對象在消亡之前要自動執行析構函數。由於malloc/free是 庫函數而不是運算符,不在編譯器控製權限之內,不能夠把執行構造函數和析構函數的任務強加於malloc/free。
6.New:new/delete是C++的運算符。可用於申請動態內存和釋放內存。C++語言需要一個能完成動態內存分配和初始化工作的運算符new, 以一個能完成清理與釋放內存工作的運算符delete。注意new/delete不是庫函數。C++程序經常要調用C函數,而C程序隻能用malloc /free管理動態內存。new 是個操作符,和什麼"+","-","="...有一樣的地位.
malloc是個分配內存的函數,供你調用的.
new是保留字,不需要頭文件支持.
malloc需要頭文件庫函數支持.new 建立的是一個對象,
malloc分配的是一塊內存.
new建立的對象你可以把它當成一個普通的對象,用成員函數訪問,不要直接訪問它的地址空間
malloc分配的是一塊內存區域,就用指針訪問好了,而且還可以在裏麵移動指針.
內存泄漏對於malloc或者new都可以檢查出來的,區別在於new可以指明是那個文件的那一行,而malloc沒有這些信息。new可以認為是malloc加構造函數的執行。new出來的指針是直接帶類型信息的。而malloc返回的都是void指針。
最後更新:2017-04-03 15:22:03