You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VirtualAlloc分配疑问:64KB粒度块部分占用后剩余区域能否分配?

关于VirtualAlloc分配已部分占用的64KB粒度内存块的问题

核心问题

若分配粒度(64KB)对应的内存块已有部分被分配,能否通过VirtualAlloc分配该块的剩余区域?

测试代码

我的代码,函数实现放在末尾。

// reserve函数:参数为目标地址和内存大小,返回long类型基地址
long base = reserve(0x660000, 0x4000);
// commit函数:参数为目标地址和内存大小,返回long类型基地址
commit(base + 0x0000, 0x10);
commit(base + 0x2000, 0x10);
// 调用QueryVirtualMemoryInformation查询指定地址内存信息
printQueryInfo(base);
// 尝试分配0x66A000地址的4KB内存,VirtualAlloc返回NULL
reserve(0x66A000, 0x1000);

控制台输出

尝试在0x660000地址分配长度为16384字节(十进制)的内存区域。
返回的基地址为:0x660000
尝试在0x660000地址提交长度为16字节(十进制)的内存区域。
返回的基地址为:0x660000
尝试在0x662000地址提交长度为16字节(十进制)的内存区域。
返回的基地址为:0x662000
查询0x660000地址的内存信息
   分配基地址:0x660000
   分配保护属性:0x4
   标记:0x1
   区域大小:0x4000
   已提交大小:0x2000
尝试在0x66A000地址分配长度为4096字节(十进制)的内存区域。
区域分配失败(base == NULL)。
返回的基地址为:0x0

疑问

我对内存分配与提交的理解如图所示,当前仅该64KB块的前5KB被分配,剩余部分是否已无法使用?

函数实现细节

以下是函数的具体实现,代码不够规范。

// 预留内存区域:参数为目标地址和大小,返回分配的基地址
long reserve(long address, long size) {
    printf("尝试在0x%lX地址分配长度为%li字节(十进制)的内存区域。\n", address, size);
    LPVOID base1 = VirtualAlloc((LPVOID)address, size, MEM_RESERVE, PAGE_READWRITE);
    if (base1 == NULL) printf("区域分配失败(base == NULL)。\n");
    long baseLong = (long)base1;
    printf("返回的基地址为:0x%lX\n", baseLong);
    return baseLong;
}

// 提交内存区域:参数为目标地址和大小,返回提交的基地址
long commit(long address, long size) {
    printf("尝试在0x%lX地址提交长度为%li字节(十进制)的内存区域。\n", address, size);
    LPVOID base1 = VirtualAlloc((LPVOID)address, size, MEM_COMMIT, PAGE_READWRITE);
    if (base1 == NULL) printf("区域提交失败(base == NULL)。\n");
    long baseLong = (long)base1;
    printf("返回的基地址为:0x%lX\n", baseLong);
    return baseLong;
}

// 查询指定地址的内存信息
void printQueryInfo(long address) {
    WIN32_MEMORY_REGION_INFORMATION regionInformation[2]; // 多预留空间,仅用sizeof(WIN32_MEMORY_REGION_INFORMATION)会报错
    long informationBufferSize;
    BOOL b = QueryVirtualMemoryInformation(
        GetCurrentProcess(),
        (LPVOID)address,
        MemoryRegionInfo,
        &regionInformation,
        28,
        &informationBufferSize
    );
    // printf("信息缓冲区大小:%li\n", informationBufferSize); // 输出值为28
    if (b == FALSE) {
        DWORD lastError = GetLastError();
        printf("QueryVirtualMemoryInformation调用失败,错误码:%i\n", (int)lastError);
    }
    else {
        printf("查询0x%lX地址的内存信息\n", address);
        printf("   分配基地址:0x%lX\n", (long)regionInformation->AllocationBase);
        printf("   分配保护属性:0x%lX\n", (long)regionInformation->AllocationProtect);
        printf("   标记:0x%lX\n", (long)regionInformation->Flags);
        printf("   区域大小:0x%zX\n", regionInformation->RegionSize);
        printf("   已提交大小:0x%zX\n", regionInformation->CommitSize);
    }
}

内存区域/提交情况可参考x64dbg截图

内容的提问来源于stack exchange,提问作者AirToTec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 02:48:09