警卫页

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

应用程序通过设置内存页面的PAGE_GUARD页面保护修饰符标志来建立【守卫页】.可以在函数VirtualAllocVirtualProtectVirtualProtectEx中指定此标志以及其他页面保护标志。除了NO_ACCESS标志之外,PAGE_GUARD标志可以与任何其他页面保护标志一起使用。

如果程序尝试访问保护页面中的地址,则操作系统将引发STATUS_GUARD_PAGE(0x80000001)异常。操作系统还清除PAGE_GUARD标志,删除内存页面的保护页面状态。系统不会停止下一次使用STATUS_GUARD_PAGE异常访问内存页的尝试。

如果在系统服务期间发生保护页异常,则服务失败,并通常返回一些故障状态指示符。由于系统还会删除相关的内存页面的保护页面状态,因为STATUS_GUARD_PAGE异常会导致同一系统服务的下次调用不会失败(除非当然有人重新建立了保护页面)。

因此,防护页面提供用于存储器页面访问的单触发警报。这对于需要监视大型动态数据结构的增长的应用程序可能是有用的。例如,有操作系统使用防护页面来实现自动堆栈检查。

以下简短程序说明了保护页面保护的单次操作,以及如何导致系统服务失败:

#include < windows.h >

#include < stdio.h >

#include < stdlib.h >

int main()

{

//局部变量

LPVOID lpvAddr;

DWORD cbSize;

BOOL vLock;

LPVOID commit;

//我们要分配的内存量

cbSize = 512;

//尝试分配一些内存

lpvAddr = VirtualAlloc(NULL,cbSize,MEM_RESERVE,PAGE_NOACCESS);

//如果我们失败了...

if(lpvAddr == NULL)

fprintf(stdout,“VirtualAlloc failed on RESERVE with%ld \\ n”,

GetLastError());

//尝试提交分配的内存

commit = VirtualAlloc(NULL,cbSize,MEM_COMMIT,PAGE_READONLY|PAGE_GUARD);

//如果我们失败了...

if(commit == NULL)

fprintf(stderr,“VirtualAlloc failed on COMMIT with%ld \\ n”,

GetLastError());

else //我们成功了

fprintf(stderr,“Committed%lu bytes at address%lp \\ n”,

cbSize,commit);

//尝试锁定已提交的内存

vLock = VirtualLock(commit,cbSize);

//如果我们失败了...

如果(!vLock)

fprintf(stderr,"Cannot lock at %lp, error = %lu\n",

commit,GetLastError());

else //我们成功了

fprintf(stderr,"Lock Achieved at %lp\n",commit);

//尝试再次锁定提交的内存

vLock = VirtualLock(commit,cbSize);

//如果我们失败了...

如果(!vLock)

fprintf(stderr,"Cannot get 2nd lock at %lp, error = %lu\n",

commit,GetLastError());

else //我们成功了

fprintf(stderr,"2nd Lock Achieved at %lp\n",commit);

} // endof函数

该程序的输出如下所示:

在地址003F0000处提交512字节

Cannot lock at 003F0000, error = 0x80000001

第二锁实现在003F0000

请注意,首次尝试锁定内存块失败,会引发STATUS_GUARD_PAGE异常。第二次尝试成功,因为第一次尝试已经切换了内存块的保护页面保护。