虚拟内存一次保留(MEM_RESERVE 可以理解为申请)最小就是 64K,一次提交(MEM_COMMIT)至少是一个页面 4K。而往往有的时候我们不知道我们到底需要多少虚拟内存才够使用,所以可能需要动态分配,下面例子演示了如何使用结构化异常机制,动态根据需要分配内存给一个不断写入新字符的空间使用。例子来自 MSDN,我只是学习抄写了一份!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <tchar.h>
#include <windows.h>

#define PAGELIMIT 80
LPTSTR lpNxtPage; // 用于记录已经提交的虚拟内存的位置
DWORD dwPages = 0; // 限制次数
DWORD dwPageSize; // 储存系统页面大小的变量

int PageFaultExceptionFilter(DWORD dwCode)
{
LPVOID lpvResult;
// 如果进程不是访问了错误的虚拟内存地址,直接返回
if (dwCode != EXCEPTION_ACCESS_VIOLATION)
{
return EXCEPTION_EXECUTE_HANDLER;
}
// 如果超出了页面限制,直接返回
if (dwPages > PAGELIMIT)
{
return EXCEPTION_EXECUTE_HANDLER;
}

// 为程序分配内存
lpvResult = VirtualAlloc((LPVOID)lpNxtPage, dwPageSize, MEM_COMMIT, PAGE_READWRITE);
if (NULL == lpvResult)
{
return EXCEPTION_EXECUTE_HANDLER;
}

// 限制变量自增
dwPages++;
// 让已提交内存位置后移
lpNxtPage += dwPageSize;

// 让程序继续执行
return EXCEPTION_CONTINUE_EXECUTION;
}

void main(void)
{
LPVOID lpvBase;
LPTSTR lpPtr;
BOOL bSuccess;
DWORD i;

SYSTEM_INFO sSysInfo;
GetSystemInfo(&sSysInfo);
dwPageSize = sSysInfo.dwPageSize;

lpvBase = VirtualAlloc(NULL, PAGELIMIT * dwPageSize, MEM_RESERVE, PAGE_NOACCESS);
lpPtr = lpNxtPage = (LPTSTR)lpvBase;
for (i = 0; i < PAGELIMIT * dwPageSize; i++)
{
__try
{
// 尚未分配内存就给赋值会触发异常
lpPtr[i] = 'a';
}
__except (PageFaultExceptionFilter(GetExceptionCode()))
{
ExitProcess(GetLastError());
}
}
bSuccess = VirtualFree(lpvBase, 0, MEM_RELEASE);
}

void ErrorExit(LPTSTR lpMsg)
{
_tprintf(_T("Error! %s with error code of %ld\n"), lpMsg, GetLastError());
exit(0);
}