Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 有关Windows用户空间内存分配限制的问题_C_Windows_Winapi_Virtual Memory - Fatal编程技术网

C 有关Windows用户空间内存分配限制的问题

C 有关Windows用户空间内存分配限制的问题,c,windows,winapi,virtual-memory,C,Windows,Winapi,Virtual Memory,我正在尝试查看Windows中可以分配内存的最大地址。我使用GetSystemInfo获取最大地址,然后尝试分配一个4KB页面。我注意到一些我以前从未见过的行为,我想知道是否有人能解释为什么会发生这种情况。首先,这里是我的测试代码: SYSTEM_INFO info; GetSystemInfo(&info); PVOID base = (PUCHAR)info.lpMaximumApplicationAddress - info.dwPageSize; SIZE_T size = i

我正在尝试查看Windows中可以分配内存的最大地址。我使用
GetSystemInfo
获取最大地址,然后尝试分配一个4KB页面。我注意到一些我以前从未见过的行为,我想知道是否有人能解释为什么会发生这种情况。首先,这里是我的测试代码:

SYSTEM_INFO info;
GetSystemInfo(&info);

PVOID base = (PUCHAR)info.lpMaximumApplicationAddress - info.dwPageSize;
SIZE_T size = info.dwPageSize;

LPVOID mem = VirtualAlloc(base, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
以下是我注意到的几件事

  • 分配的大小实际上大于一页的4KB,即64KB。为什么?
  • 分配的基址是
    0x7FFFFFFFF0000
    。分配大小为64KB时,结束地址为
    7fffffff0000
    ,仅比最高用户地址多一个字节。这不是越界了吗
  • 我在x64 Windows上执行此操作

    如果我能理解为什么会这样,那就太好了

    分配的大小实际上大于一页的4KB,即64KB。为什么?

    您没有考虑
    info.dwAllocationGranularity
    。页面大小可能是4K,但粒度是64K。页面分配必须是粒度的偶数倍。因此,您指定的基址将向下舍入到下一个最低粒度边界。文档中对此进行了讨论:

    lpAddress

    要分配的区域的起始地址。如果内存被保留,指定的地址将向下舍入到分配粒度的最近倍数。如果内存已被保留且正在提交,则地址将向下舍入到下一页边界。要确定主机上的页面大小和分配粒度,请使用函数。如果此参数为空,系统将确定在何处分配区域

    另见

    在您的情况下,
    info.lpMaximumApplicationAddress
    很可能是
    0x7FFFFFEFFFF
    (64K小于8TB,这是Windows 8及更早版本支持的最大内存;Windows 8.1的缓冲限制为128TB)。从中减去4K即为
    0x7FFFFFEEFFF
    ,然后四舍五入为
    0x7FFFFFF0000
    ,是64K的偶数倍

    分配的基址是0x7FFFFFF0000。分配大小为64KB时,结束地址为7FFFFF0000,仅比最高用户地址多一个字节。这不是越界了吗


    <代码>信息.LpMulMax Apple TrimeAdv>代码>类似于一个数组的1-前端指针,或一个标准C++容器的<代码>端()/<代码>迭代器。这是一个最大地址,你不应该去过去,甚至取消引用。您最多可以访问该最大地址的内存地址,但不包括它。

    解释得很清楚,谢谢!