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

Windows x64下指定内存范围VirtualAlloc分配失败排查

VirtualAlloc返回ERROR_INVALID_ADDRESS的可能原因(指定基地址附近分配场景)
  • 地址未对齐到系统分配粒度
    VirtualAlloc要求分配的起始地址必须严格对齐到系统的dwAllocationGranularity(可通过GetSystemInfo获取,Windows下通常为64KB即0x10000)。即便你找到的MEM_FREE区域空间足够,只要起始地址没满足对齐要求,就会直接返回ERROR_INVALID_ADDRESS。比如你选中的起始地址是0x007FFFFFFF401234,而系统分配粒度是64KB,这个地址就不符合对齐规则。

  • 目标地址超出进程虚拟地址空间边界
    64位Windows进程的用户态虚拟地址空间通常上限为0x00007FFFFFFFFFFF(不同系统版本可能略有差异),你的基地址0x007FFFFFFF400000已经非常接近这个上限。如果计算后的最大地址超出了这个边界,即便VirtualQuery返回该区域为MEM_FREE,进程也无法在这个范围分配内存,因为这部分地址属于内核态预留空间,用户态进程无权访问。

  • MEM_FREE区域属于系统预留不可分配范围
    有些被标记为MEM_FREE的地址区域,实际上是系统预留的特殊范围(比如靠近内核态的地址段、硬件映射区域等)。这类区域虽然在VirtualQuery中显示为未被占用,但用户态进程无法通过VirtualAlloc进行保留或提交操作,强行分配就会触发ERROR_INVALID_ADDRESS。

  • VirtualAlloc参数组合错误
    当指定lpAddress参数时,必须确保参数组合逻辑正确:

    • 必须搭配MEM_RESERVE或MEM_RESERVE | MEM_COMMIT标志,不能单独用MEM_COMMIT指定非NULL的lpAddress;
    • 如果指定的地址范围中存在部分已被保留/提交的页,哪怕大部分是MEM_FREE,也会导致分配失败;
    • 若同时使用MEM_TOP_DOWN等会改变分配策略的标志,可能与你指定地址的逻辑冲突,导致地址无效。
  • 地址范围计算逻辑有误
    你提到的最大地址计算方式基地址 + (1LL << 31) - size可能存在偏差:x86/x64的32位相对跳转使用的是有符号位移,有效范围是-2^31到2^31 -1,且位移是相对于当前指令的下一条指令地址。如果你的基地址是指令所在地址,目标地址的正确范围应该是指令地址 + 下一条指令偏移 - 2^31到指令地址 + 下一条指令偏移 + 2^31 -1。若计算错误导致目标地址落在系统限制的不可分配区域,自然会分配失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 04:10:02