了解 VirtualAlloc 中的基址

Understanding base addresses in VirtualAlloc

本文关键字:VirtualAlloc 了解      更新时间:2023-10-16

在我的应用程序中,我试图在启动时通过VirtualAlloc分配一个大块内存(大约1GB-2GB(,然后我可以将其划分为在应用程序的其余部分使用。 在调试模式下,我想在 VirtualAlloc 调用中传递一个基址,以保持指针地址一致,以便于调试,但我正在努力理解什么是我可以使用的有效基址。

下面是进行分配的代码片段

s32 CALLBACK WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdLine, s32 showCode)
{
SYSTEM_INFO info = {};
GetSystemInfo(&info);
// In my case info.lpMinimumApplicationAddress gives me 64kb
LPVOID base = info.lpMinimumApplicationAddress;
u32 totalSize = MEGABYTES(8);
void *test = VirtualAlloc(base, totalSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
...
}

该应用程序是在 64 位版本的 Windows 上运行的 x86,根据我发现的以下信息: https://www.tenouk.com/WinVirtualAddressSpace.html

仅为应用程序保留的虚拟内存空间应介于 4MB 到 2GB 之间。 但是,当我尝试分配少量内存时,如上面的代码片段所示,基址为 64KB(如系统信息所示(或根据引用的网站在 4MB 左右,VirtualAlloc 返回 0。 我尝试使用 VirtualQueryEx 调查虚拟内存空间,我能找到的最大内存块大小约为 2GB,但基址为 2GB。 根据上述信息,这意味着我正在分配给系统内存,这可能会有潜在危险?

简而言之,我想知道是否有人可以澄清我在该网站上引用的信息是否准确,以及拥有 1GB 或 2GB 的大基址是否可以安全使用? 我对解决方案的唯一其他想法是扫描虚拟地址空间以查找足够大的块,并使用我找到的第一个块作为基址,但我不确定该基址是否会在连续运行之间保持一致为了调试。

提前谢谢。

链接的文章适用于 32 位模式。在 64 位模式下,保留地址从 128 TB 开始。以下是 MSDN 对此的看法:

对于 32 位进程,虚拟地址空间通常是 2 GB 的范围,0x00000000到 0x7FFFFFFF。对于 64 位 Windows 上的 64 位进程,虚拟地址空间是 128 TB 的范围 0x000'00000000 到 0x7FFF'FFFFFFFFFFF。虚拟地址范围有时称为虚拟内存范围。有关详细信息,请参阅内存和地址空间限制。

所以你是安全的。

但是您根本不应该关心或探测基址 - 只需将NULL作为基址传递,VirtualAlloc就会为您选择一个:

lpAddress

要分配的区域的起始地址。如果正在预留内存,则指定的地址将向下舍入到分配粒度的最接近的倍数。 . . .如果此参数为NULL,则系统将确定分配区域的位置。