使用虚拟内存函数

【勇芳软件工作室】汉化HomePreviousNext

本节介绍如何使用虚拟内存功能进行动态分配。

以下示例说明了VirtualAllocVirtualFree函数根据动态数组的需要预留和提交内存时的使用。首先,VirtualAlloc被调用来保留一个被指定为NULL地址参数的页面块,从而迫使内核确定块的位置。稍后,只要有必要从该保留区域提交页面,就会调用VirtualAlloc,并指定要提交的下一页的基址。

该示例使用尝试 - 结构化异常处理语法来从保留区域提交页面。每当执行尝试块期间发生页错误异常时,将执行块之前的表达式中的过滤器函数。如果过滤器功能可以分配另一个页面,则在发生异常的时候,在尝试块中继续执行。否则,将执行块中的异常处理程序。有关结构化异常处理的更多信息,请参阅结构化异常处理.

作为动态分配的替代方法,该过程可以简单地提交整个区域,而不仅仅是保留它。但是,提交该区域将消耗可能不需要的物理存储,从而使其不能被其他进程使用。

该示例使用VirtualFree完成保留和提交的页面后,释放它们。该函数被调用两次:首先解除提交的页面,并再次释放保留页面的整个区域。

#define PAGESIZE 0x1000

/* Reserve pages in the process's virtual address space.

INT PageFaultExceptionFilter(DWORD);

VOID MyErrorExit(LPTSTR);

LPTSTR lpNxtPage;

DWORD dwPages = 0;

VOID UseDynamicVirtualAlloc(VOID){

LPVOID lpvBase;

LPTSTR lpPtr;

BOOL bSuccess;

DWORD i;

/ *保留进程虚拟地址空间中的页面。*/

lpvBase = VirtualAlloc(

NULL,/ *系统选择地址* /

PAGELIMIT * PAGESIZE,/ *大小分配* /

MEM_RESERVE,/ *分配保留页面* /

PAGE_NOACCESS); /* protection = no access */

if (lpvBase == NULL )

MyErrorExit("VirtualAlloc reserve");

lpPtr = lpNxtPage = (LPTSTR) lpvBase;

/*

*使用try-except结构化异常处理时

*访问页面。如果发生页错误,

*执行异常过滤器以提交另一个页面

*从预留的页面块。

*/

for (i=0; i < PAGELIMIT*PAGESIZE; i++) {

尝试{

/ *写入内存。*/

lpPtr[i] = 'a';

}

/*

*如果有页面错误,请提交另一个页面

* 然后再试一次。

*/

except(PageFaultExceptionFilter(

GetExceptionCode())){

/*

*只有过滤功能才执行

*提交下一页不成功。

*/

ExitProcess( GetLastError() );

}

}

/ *完成使用后,释放页面块。*/

/ *首先,解决承诺的页面。*/

bSuccess = VirtualFree(

lpvBase,/ *块的地址* /

dwPages * PAGESIZE,/ *已提交页面的字节* /

MEM_DECOMMIT); /* decommit the pages */

/ *释放整个块。*/

如果(bSuccess)

bSuccess = VirtualFree(

lpvBase,/ *块的地址* /

0,/ *释放整个块* /

MEM_RELEASE); /* releases the pages */

}

INT PageFaultExceptionFilter(DWORD dwCode){

LPVOID lpvResult;

/ *如果异常不是页面错误,请退出。*/

if (dwCode != EXCEPTION_ACCESS_VIOLATION) {

printf("exception code = %d\n", dwCode);

return EXCEPTION_EXECUTE_HANDLER;

}

printf("page fault\n");

/ *如果预留页面用完,请退出。*/

if (dwPages >= PAGELIMIT) {

printf("out of pages\n");

return EXCEPTION_EXECUTE_HANDLER;

}

/ *否则,提交另一个页面。*/

lpvResult = VirtualAlloc(

(LPVOID)lpNxtPage,/ *下一页提交* /

PAGESIZE,/ *页面大小,以字节为单位* /

MEM_COMMIT,/ * alloc commit page * /

PAGE_READWRITE); /* read-write access */

if (lpvResult == NULL ) {

printf("VirtualAlloc failed\n");

return EXCEPTION_EXECUTE_HANDLER;

}

/*

*增加页数,并提高lpNxtPage

*到下一页。

*/

dwPages++;

lpNxtPage += PAGESIZE;

/ *继续执行页面发生故障。*/

return EXCEPTION_CONTINUE_EXECUTION;

}