【问题标题】:Understanding base addresses in VirtualAlloc了解 VirtualAlloc 中的基地址
【发布时间】:2020-09-22 06:05:56
【问题描述】:

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

这是发生分配的代码的 sn-p

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 之间。但是,当我尝试在上面的 sn-p 中分配少量内存时,其基地址为 64KB(由系统信息给出)或根据引用的网站 VirtualAlloc 返回 0 或 4MB 左右。我已经尝试使用 VirtualQueryEx 调查虚拟内存空间,我能找到的最大内存块大小约为 2GB,但基址为 2GB。根据上面的信息,这意味着我正在分配可能有潜在危险的系统内存?

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

提前致谢。

【问题讨论】:

    标签: c++ memory x86 windows-10-desktop virtual-address-space


    【解决方案1】:

    链接的文章适用于 32 位模式。在 64 位模式下,保留地址从 128 TB 开始。以下是MSDN says 的相关内容:

    对于 32 位进程,虚拟地址空间通常是 2 GB 范围 0x00000000 到 0x7FFFFFFF。对于 64 位 Windows 上的 64 位进程,虚拟地址空间是 128 TB 范围 0x000'00000000 到 0x7FFF'FFFFFFFF。虚拟地址范围有时称为虚拟内存范围。如需更多信息,请参阅Memory and Address Space Limits

    所以你是安全的。

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

    lpAddress

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

    【讨论】:

    • 非常感谢您的快速响应和清理。但是在 VirtualAlloc 中有一个固定的基地址会保持指针值一致,这对调试很有用吗?
    • 是的,但不幸的是,这是有问题的,因为程序本身以及它使用的任何共享库都是在随机地址加载的(称为ASLR 的安全功能)。所以任何固定的基地址最终都会被占用。
    • 啊,我明白了,有道理。感谢您的澄清:)
    猜你喜欢
    • 1970-01-01
    • 2013-07-18
    • 2016-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    • 1970-01-01
    • 2020-08-18
    相关资源
    最近更新 更多