利用结构化异常实现动态分配虚拟内存

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

#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);
}

发表评论