【问题标题】:Why does VirtualAlloc fail for 2GB even when running as 64bit process?即使作为 64 位进程运行,为什么 VirtualAlloc 也会失败 2GB?
【发布时间】:2015-08-17 16:56:31
【问题描述】:

运行良好

    int GB = 2;
    int bytes = GB * 1024 * 1024 * 1024;

    LPVOID memory = VirtualAlloc(
        0,
        bytes-1, // 2GB - 1
        MEM_COMMIT,
        PAGE_READWRITE);

在这里,只要我达到 2GB,它就会失败

    int GB = 2;
    int bytes = GB * 1024 * 1024 * 1024;

    LPVOID memory = VirtualAlloc(
        0,
        bytes, // 2GB
        MEM_COMMIT,
        PAGE_READWRITE);

带有 Windows 错误消息“参数不正确”。为什么会这样?其实我想分配更多的虚拟内存。

【问题讨论】:

  • 我回滚了编辑,因为它改变了问题,并使答案无效(intlong 是不同的类型,即使在 LLP64 实现上的基本原理相同)。
  • 对,这样可能更容易理解。

标签: winapi memory-management virtual-memory


【解决方案1】:

int 是 Windows 平台上的 32 位有符号数量。 2GB - 1 是可表示的最大正值,而 2GB 具有最高位设置,并被解释为负值。

值的二进制表示是:

 3         2         1         0
10987654321098765432109876543210

01111111111111111111111111111111  2GB - 1
10000000000000000000000000000000  2GB

当值 2GB 传递给VirtualAlloc 时,它会进行符号扩展并转换为SIZE_T。结果值是二进制表示的1111111111111111111111111111111110000000000000000000000000000000(十进制:18446744071562067968,十六进制:0xffffffff80000000)。换句话说:巨大。

如果您需要分配 2GB 或更多,请使用 SIZE_T 而不是 int。它在 basetsd.h 中声明如下:

typedef ULONG_PTR SIZE_T, *PSIZE_T;

它足够大,可以识别跨越指针整个范围的计数或范围。

【讨论】:

  • 呃,愚蠢的我,对不起,你当然是完全正确的。问题是,更改为 long 会导致完全相同的结果。目前看起来,该进程并没有真正在 64 位下运行。
  • @citykid:使用 Microsoft 编译器时,long 也是 32 位的。如果您可以使用 C++11 功能,则必须改用 unsigned long long。或者干脆使用SIZE_T
  • @IInspectable Pedantry 模式开启。 long 对于任何面向 Windows 的健全编译器来说都是 32 位。决定这一点的是平台,而不是编译器。
  • @DavidHeffernan:你说得对,控制数据类型大小的是目标平台(参考:Abstract Data Models)。对于任何感兴趣的人:Why did the Win64 team choose the LLP64 model?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-06
  • 2012-08-21
  • 2021-06-20
  • 2014-02-03
  • 2018-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多