Reserving and Committing Memory
The following example illustrates the use of the VirtualAlloc and VirtualFree functions in reserving and committing memory as needed for a dynamic array. First, VirtualAlloc is called to reserve a block of pages with NULL specified as the base address parameter, forcing the system to determine the location of the block. Later, VirtualAlloc is called whenever it is necessary to commit a page from this reserved region, and the base address of the next page to be committed is specified.
下面的例子闡明了使用VirtualAlloc和 VirtualFree函數為一個動態數組預留和調撥所需的記憶體。首先,調用VirtualAlloc預留一塊頁,指定基址參數為NULL,由系統確定塊的位置。然後,VirtualAlloc在任何必要的時候從這個預留的地區內調撥一個頁面,同時下一個要被調撥的頁面的基址也已經被指定了。
The example uses structured exception-handling syntax to commit pages from the reserved region. Whenever a page fault exception occurs during the execution of the __try block, the filter function in the expression preceding the __except block is executed. If the filter function can allocate another page, execution continues in the __try block at the point where the exception occurred. Otherwise, the exception handler in the __except block is executed. For more information, seeStructured Exception Handling.
本例用結構化異常處理語句從預留地區調撥頁面。只要執行__try塊過程中發生一個頁錯誤例外,運算式中先於__except 塊的過濾函數會被執行。如果這個過濾函數能夠重新分配一個頁面,將從__try塊中發生異常的地方繼續執行。否則__except 塊中的例外處理被執行。更多資訊,見結構化異常處理。
As an alternative to dynamic allocation, the process can simply commit the entire region instead of only reserving it. However, committing the region consumes physical storage that might not be needed, making it unavailable for use by other processes.
對於一個動態分配事件,進程可以簡單的直接把整個地區調撥而不是預留。然而,調撥這個地區不必要地消耗了實體記憶體,使其很難再被其他進程使用。
The example uses VirtualFree to free the reserved and committed pages when it is finished with them. The function uses MEM_RELEASE to decommit and release the entire region of reserved and committed pages.
本例使用VirtualFree 來釋放被預留和調撥結束的頁面。這個函數使用MEM_RELEASE 取消調撥和釋放整個被預留和調撥的頁面地區。
// A short program to demonstrate dynamic memory allocation using // a structured exception handler. #include <windows.h>#include <stdio.h> // for printf#include <stdlib.h> // for exit#define PAGELIMIT 80 // ask for this many pagesLPTSTR lpNxtPage; // address of the next page to ask forDWORD dwPages = 0; // count of pages gotten so farDWORD dwPageSize; // the page size on this computerINT PageFaultExceptionFilter(DWORD dwCode){ LPVOID lpvResult; // If the exception is not a page fault, exit. if (dwCode != EXCEPTION_ACCESS_VIOLATION) { printf("Exception code = %d/n", dwCode); return EXCEPTION_EXECUTE_HANDLER; } printf("Exception is a page fault/n"); // If the reserved pages are used up, exit. if (dwPages >= PAGELIMIT) { printf("Exception: out of pages/n"); return EXCEPTION_EXECUTE_HANDLER; } // Otherwise, commit another page. lpvResult = VirtualAlloc( (LPVOID) lpNxtPage, // next page to commit dwPageSize, // page size, in bytes MEM_COMMIT, // allocate a committed page PAGE_READWRITE); // read/write access if (lpvResult == NULL ) { printf("VirtualAlloc failed/n"); return EXCEPTION_EXECUTE_HANDLER; } else { printf ("Allocating another page./n"); } // Increment the page count, and advance lpNxtPage to the next page. dwPages++; lpNxtPage += dwPageSize; // Continue execution where the page fault occurred. return EXCEPTION_CONTINUE_EXECUTION;}VOID ErrorExit(LPTSTR oops){ printf ("Error! %s with error code of %ld/n", oops, GetLastError ()); exit (0);}VOID main(VOID){ LPVOID lpvBase; // base address of the test memory LPTSTR lpPtr; // generic character pointer BOOL bSuccess; // flag DWORD i; // generic counter SYSTEM_INFO sSysInfo; // useful information about the system GetSystemInfo(&sSysInfo); // populate the system information structure printf ("This computer has a page size of %d./n", sSysInfo.dwPageSize); dwPageSize = sSysInfo.dwPageSize; // Reserve pages in the process's virtual address space. lpvBase = VirtualAlloc( NULL, // system selects address PAGELIMIT*dwPageSize, // size of allocation MEM_RESERVE, // allocate reserved pages PAGE_NOACCESS); // protection = no access if (lpvBase == NULL ) ErrorExit("VirtualAlloc reserve failed"); lpPtr = lpNxtPage = (LPTSTR) lpvBase; // Use structured exception handling when accessing the pages. // If a page fault occurs, the exception filter is executed to // commit another page from the reserved block of pages. for (i=0; i < PAGELIMIT*dwPageSize; i++) { __try { // Write to memory. lpPtr[i] = 'a'; } // If there's a page fault, commit another page and try again. __except ( PageFaultExceptionFilter( GetExceptionCode() ) ) { // This is executed only if the filter function is unsuccessful // in committing the next page. ExitProcess( GetLastError() ); } } // Release the block of pages when you are finished using them. bSuccess = VirtualFree( lpvBase, // base address of block 0, // bytes of committed pages MEM_RELEASE); // decommit the pages printf ("Release was %s./n", bSuccess ? "successful" : "unsuccessful" );}