Windows記憶體配置方式
- Win32的堆分配函數
每一個進程都可以使用堆分配函數建立一個私人的堆──調用進程地址空間的一個或者多個頁面。DLL建立的私人堆必定在調用DLL的進程的地址空間內,只能被調用進程訪問。
HeapCreate用來建立堆;HeapAlloc用來從堆中分配一定數量的空間,HeapAlloc分配的記憶體是不能移動的;HeapSize可以確定從堆中分配的空間的大小;HeapFree用來釋放從堆中分配的空間;HeapDestroy銷毀建立的堆。
- Windows傳統的全域或者局部記憶體配置函數
由於Win32採用平面記憶體結構模式,Win32下的全域和局部記憶體函數除了名字不同外,其他完全相同。任一函數都可以用來分配任意大小的記憶體(僅僅受可用實體記憶體的限制)。用法可以和Win16下基本一樣。
Win32下保留這類函數保證了和Win16的相容。
- C語言的標準記憶體配置函數
C語言的標準記憶體配置函數包括以下函數:
malloc,calloc,realloc,free,等。
這些函數最後都映射成堆API函數,所以,malloc分配的記憶體是不能移動的。這些函數的調式版本為
malloc_dbg,calloc_dbg,realloc_dbg,free_dbg,等。
- Win32的虛擬記憶體分配函數
虛擬記憶體API是其他API的基礎。虛擬記憶體API以頁為最小分配單位,X86上頁長度為4KB,可以用GetSystemInfo函數提取頁長度。虛擬記憶體分配函數包括以下函數:
- LPVOID VirtualAlloc(LPVOID lpvAddress,
DWORD cbSize,
DWORD fdwAllocationType,
DWORD fdwProtect);
該函數用來分配一定範圍的虛擬頁。參數1指定起始地址;參數2指定分配記憶體的長度;參數3指定分配方式,取值 MEM_COMMINT或者MEM_RESERVE;參數4指定控制訪問本次分配的記憶體的標識,取值為PAGE_READONLY、 PAGE_READWRITE或者PAGE_NOACCESS。
- LPVOID VirtualAllocEx(HANDLE process,
LPVOID lpvAddress,
DWORD cbSize,
DWORD fdwAllocationType,
DWORD fdwProtect);
該函數功能類似於VirtualAlloc,但是允許指定進程process。VirtaulFree、VirtualProtect、VirtualQuery都有對應的擴充函數。
- BOOL VirtualFree(LPVOID lpvAddress,
DWORD dwSize,
DWORD dwFreeType);
該函數用來回收或者釋放分配的虛擬記憶體。參數1指定希望回收或者釋放記憶體的基地址;如果是回收,參數2可以指向虛 擬位址範圍內的任何地方,如果是釋放,參數2必須是VirtualAlloc返回的地址;參數3指定是否釋放或者回收記憶體,取值為 MEM_DECOMMINT或者MEM_RELEASE。
- BOOL VirtualProtect(LPVOID lpvAddress,
DWORD cbSize,
DWORD fdwNewProtect,
PDWORD pfdwOldProtect);
該函數用來把已經分配的頁改變成保護頁。參數1指定分配頁的基地址;參數2指定保護頁的長度;參數3指定頁的保護屬性,取值PAGE_READ、PAGE_WRITE、PAGE_READWRITE等等;參數4用來返回原來的保護屬性。
- DWORD VirtualQuery(LPCVOID lpAddress,
PMEMORY_BASIC_INFORMATION lpBuffer,
DWORD dwLength
);
該函數用來查詢記憶體中指定頁的特性。參數1指向希望查詢的虛擬位址;參數2是指向記憶體基本資料結構的指標;參數3指定查詢的長度。
- BOOL VirtualLock(LPVOID lpAddress,DWORD dwSize);
該函數用來鎖定記憶體,鎖定的記憶體頁不能交換到頁檔案。參數1指定要鎖定記憶體的起始地址;參數2指定鎖定的長度。
- BOOL VirtualUnLock(LPVOID lpAddress,DWORD dwSize);
參數1指定要解鎖的記憶體的起始地址;參數2指定要解鎖的記憶體的長度。
c++中的記憶體配置方式
記憶體的三種分配方式:1. 從靜態儲存區配置:此時的記憶體在程式編譯的時候已經分配好,並且在程式的整個運行期間都存在。全域變數,static變數等在此儲存。2. 在棧區分配:相關代碼執行時建立,執行結束時被自動釋放。局部變數在此儲存。棧記憶體配置運算內建於處理器的指令集中,效率高,但容量有限。3. 在堆區分配:動態分配記憶體。用new/malloc時開闢,delete/free時釋放。生存期由使用者指定,靈活。但有記憶體泄露等問題。常見記憶體錯誤及對策1. 記憶體配置未成功,卻被使用。對策:使用記憶體之前檢查是否分配成功。用p!=NULL判斷。2. 記憶體配置成功,未初始化就被使用。記憶體的預設值沒有統一的標準。大部分編譯器以0作為初始值,但不完全是。對策:記憶體初始化時賦初值。3. 記憶體操作越界。對策:只能是小心了。4. 釋放了記憶體,仍然使用。(1) 使用顯示delete和free的野指標。對策:釋放完記憶體,將指標置為NULL。(2) 使用隱式delete和free的野指標。主要是指函數返回指向棧記憶體的指標或引用。對策:當然是不要返回就可以了。5. 未釋放記憶體,導致記憶體泄露。用new/malloc開闢了記憶體,沒用delete/free釋放.對策:new和delete的個數一定相同;malloc和free的個數一定相同;new[]和[]delete一定對應。