Winapi 为什么对于大于0x6FFFFFFFF的lpAddress,VirtualAlloc会失败
我想尝试通过使用VirtualAlloc将尽可能接近64位的地址映射到有效内存中,来了解在64位C程序中可以指向的“远”的限制 我设法找到了Winapi 为什么对于大于0x6FFFFFFFF的lpAddress,VirtualAlloc会失败,winapi,64-bit,Winapi,64 Bit,我想尝试通过使用VirtualAlloc将尽可能接近64位的地址映射到有效内存中,来了解在64位C程序中可以指向的“远”的限制 我设法找到了0x6ffffffffffff,这是一个42位的地址,但上面的任何数字都会导致分配失败,错误代码为0x57(参数不正确) 这是我的代码: #include <Windows.h> #include <stdio.h> int main(int argc, char **argv) { LPVOID mem; WCHA
0x6ffffffffffff
,这是一个42位的地址,但上面的任何数字都会导致分配失败,错误代码为0x57(参数不正确)
这是我的代码:
#include <Windows.h>
#include <stdio.h>
int main(int argc, char **argv)
{
LPVOID mem;
WCHAR message[] = L"Hello, World!";
mem = VirtualAlloc (
(LPVOID)0x00006ffffffffff,
4096,
MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE
);
if (mem == 0) {
wprintf(L"%x.\n", GetLastError());
system("pause");
exit(-1);
}
memcpy(mem, message, sizeof(message));
wprintf(L"[%llx] -> %ls\n", mem, mem);
system("pause");
return 0;
}
#包括
#包括
int main(int argc,字符**argv)
{
LPVOID-mem;
WCHAR消息[]=L“你好,世界!”;
mem=虚拟现实(
(LPVOID)0x00006FFFFFFFF,
4096,
保留|承诺|,
页面\读写
);
if(mem==0){
wprintf(L“%x.\n”,GetLastError());
系统(“暂停”);
出口(-1);
}
memcpy(mem,message,sizeof(message));
wprintf(L“[%llx]->%ls\n”,mem,mem);
系统(“暂停”);
返回0;
}
为什么我不能在上面使用VirtualAlloc
0x6ffffffffff
?原因是您请求的地址超出了可用范围。虽然理论上有64位的可用地址范围,但实际上并非所有的可用地址范围都适用于用户模式应用程序。通过调用GetSystemInfo
并检查lpMinimumApplicationAddress
和lpmaximuapplicationaddress
的值,可以找到允许的范围。如果试图保留此范围之外的地址,则调用VirtualAlloc
将失败,错误代码设置为error\u INVALID\u参数
请注意,这些最小值和最大值并不精确。当接近极限时,您将开始观察
ERROR\u INVALID\u参数。您当前的CPU只有48位地址空间,至少在其他系统(不确定Windows)上,一半的地址空间通常保留给内核。内核难道没有自己的地址空间可供使用吗?在我的进程的地址空间中,这些字节是为特定目的保留的吗?我在考虑堆栈,但我不确定如何测试它。不确定windows,但对于Linux,堆栈从高地址开始,然后向下扩展。您试图保留的页面可能已被锁定,用作堆栈页面或类似页面。这在某种程度上与错误代码冲突,但如果在alloc函数调用中硬编码42位限制,则可能仍然是正确的。请尝试调用GetSystemInfo
,并查看lpMaximumApplicationAddress
@Dmitry内核可能有自己的地址空间,但在用户区和内核之间传递数据会非常痛苦,因此,这通常是不做的。只为内核保留一部分地址空间要容易得多(就像我提到的,我不知道Windows是这么做的,但其他人都这么做,因为这样更简单、更快)。如果您想知道为什么它只有48个,那是因为没有x86 CPU实现更多。我的lpMaximumApplicationAddress是0x7ffffffffff
这是0xffff0000
低于最大值。似乎有点奇怪。如果它们将被保留,它还会给出错误0x57吗?好的,因此解释肯定是地址已被保留。如果地址已被保留,错误将是487-错误\u无效\u地址
。我猜某些特定窗口上存在一些bug或钩子,因为在win7+(不检查vista)上分配的地址最多为000007ffffffff
,而从win8so开始分配的地址最多为00007ffffffff
,所以如果您试图保留已保留的地址,则必须使用语句2,然后对VirtualAlloc的调用将失败,错误代码设置为error\u INVALID\u ADDRESS
当您接近极限时,您将开始观察error\u INVALID\u参数
-现在(最多赢10次)正好在64K上。当lpAddress
或lpAddress+dwSize
>MM\u最高值\u VAD\u地址时,exist和VirtualAlloc返回ERROR\u INVALID\u参数
-