gpt4 book ai didi

c++ - VirtualAlloc 的困惑 - 它只适用于页面吗?

转载 作者:可可西里 更新时间:2023-11-01 09:45:06 27 4
gpt4 key购买 nike

我需要使用 VirtualAlloc 为我的项目分配可执行内存,以便 JIT 将自定义脚本格式重新编译为 x86/etc。但我感到困惑的是,其他人似乎都没有注意到,而且它的行为似乎明显缺乏细节。

我知道它分配“虚拟”内存,这意味着它可以是物理上的任何东西(RAM/磁盘),但在使用时它可以简单地被视为“内存”。但是,例如,如果我做类似的事情:

#define MB 1024*1024
auto pAddr = VirtualAlloc(NULL, 8*MB, MEM_RESERVE, PAGE_NOACCESS);
VirtualAlloc(pAddr + 4*MB, 1*MB, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // commit 1MB, 4MB's into the reserved memory

是只使用了 1MB 还是 5MB?显然,我并不期望它是 5MB - 我只是不知道在这种看似显而易见的情况下会发生什么。有效吗?保留内存中的任何范围都可以自由提交和取消提交吗?更重要的是,它可以乱序使用还是应该增量分配(根据 MSDN 文档,看起来你可以用它来做)。还是 VirtualAlloc 只对一次分配“页面”感到满意?

我发现的每个示例似乎只对向我展示如何分配页面感兴趣——这可能只是最基本的用途,但远非最实用——但我想用它来为脚本分配编译代码,这可能是偶尔在执行期间重新编译。我需要尝试为这些分配创建某种接口(interface),这样我就可以简单地说“为这个脚本编译提供一些内存”,它会自动返回以前未使用的提交空间或提交一些新空间 - 所以任何提示如何最好地从虚拟内存分配(例如,最好不要取消提交可能会再次提交的内存?)也将受到赞赏。

最佳答案

好的;我认为我明白你的意思,我希望这会澄清事情。

从概念上讲,VirtualAlloc 在单独的页面上工作。

为简单起见,让我们考虑一个 32 位 x86 进程。虚拟地址空间是从第 0 页到第 1048575 页的一系列页面。这些页面中的每一个都可能保留也可能不保留;如果保留,则可能会或可能不会提交。 (如果提交,它也将有零个或多个内存保护选项,并且页面可能处于各种其他状态,但我们现在几乎可以忽略所有这些。)

无法只保留或提交页面的一部分,或者同一页面的两个部分具有不同的内存保护选项。相反,保留和/或提交的页面是否连续并不重要。

如果您使用特定的起始地址和区域大小调用 VirtualAlloc,那么它会作用于指定虚拟地址区域中包含一个或多个字节的每一页。地址和大小用于计算要作用于哪些页面。参数是地址而不是页码的唯一原因是为了简化程序员的工作。

从概念上讲,一次覆盖多个页面的 VirtualAlloc 调用等同于为每个页面调用一次 VirtualAlloc。唯一的区别(效率除外)是一次对多个页面进行操作是原子的,因此在整个范围内要么失败要么成功。

请特别注意,如果您成功多次调用 VirtualAlloc 覆盖连续的页面,则无法告诉后记这些页面是单独分配的。操作系统只记得页面处于什么状态,而不是它是如何到达那里的。 [附录:糟糕;这是错误的。 VirtualQuery 的文档说它可以判断连续的页面是否属于同一分配。也许它们被标记了唯一的分配 ID 或其他东西。我不相信内存管理器实际上使用了这些信息,但显然它 被保留了。]

请记住,HeapCreate 函数已经允许您创建一个堆,其内存块允许代码执行。除非您的应用程序有非常特殊的需求,否则您不太可能通过编写自己的堆管理器获得任何好处。

关于c++ - VirtualAlloc 的困惑 - 它只适用于页面吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22183228/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com