【问题标题】:For what do I need to use VirtualAlloc/VirtualAllocEx?我需要使用 VirtualAlloc/VirtualAllocEx 做什么?
【发布时间】:2013-07-05 00:02:39
【问题描述】:

我需要使用 VirtualAlloc/VirtualAllocEx 做什么?

一个例子,我发现的一个案例 - 如果我分配了 4 GB 的虚拟内存,那么如果我不使用所有这些,那么我不会花费物理内存,如果我调整我的数组大小,我 不需要重新分配和复制旧数据到新数组。

struct T_custom_allocator; // which using VirtualAllocEx()
std::vector<int, T_custom_allocator> vec;
vec.reserve(4*1024*1024*1024);  // allocated virtual memory (physical memory is not used)
vec.resize(16384); // allocated 16KB of physical memory
// ...
vec.resize(32768); // allocated 32KB of physical memory 
                   // (no need to copy of first 16 KB of data)

如果我使用标准分配器,我在调整大小时需要复制数据

std::vector<int> vec;
vec.resize(16384); // allocated 16KB of physical memory
// ...
vec.resize(32768); // allocated 32KB of physical memory 
                   // and need to copy of first 16 KB of data

或者使用标准分配器,我必须花费 4GB 物理内存:

std::vector<int> vec;
vec.reserve(4*1024*1024*1024);  // allocated 4GB of physical memory
vec.resize(16384); // no need to do, except changing a local variable of size
// ...
vec.resize(32768); // no need to do, except changing a local variable of size

但是,为什么这比 realloc() 更好? http://www.cplusplus.com/reference/cstdlib/realloc/

还有其他使用 VirtualAlloc[Ex] 的情况吗?

【问题讨论】:

    标签: c++ winapi virtualalloc


    【解决方案1】:

    VirtualAllocEx 的另一个用途尚未提及,它是在另一个进程的地址空间中分配内存。请注意,第一个参数是进程的句柄 - 该函数在该进程的虚拟地址空间内分配内存。

    我以前在将代码注入另一个进程时使用过这个,通过在目标进程中强制调用LoadLibrary。基本步骤如下:

    1. 获取目标进程的进程ID(例如GetWindowThreadProcessId之类的)。
    2. 使用OpenProcess获取具有适当权限的进程句柄。
    3. 使用VirtualAllocEx 在该进程中分配一些内存。
    4. 使用WriteProcessMemory 将您的DLL 名称复制到该内存中。
    5. 使用GetProcAddress获取LoadLibrary函数的地址。
    6. 调用CreateRemoteThread 以在目标进程中启动LoadLibrary 调用,线程参数是您使用VirtualAllocEx 分配的内存(包含DLL 的名称)。

    并不是说您需要了解所有这些,但我认为这是一个有趣的用例。

    【讨论】:

      【解决方案2】:

      VirtualAllocVirtualAllocEx 在非常简单的术语中分配原始页面,从mallocGlobalAlloc 的所有其他内存函数都在下面使用VirtualAllocExVirtualAlloc 的问题在于它基本上是原始内存,没有可用的重新分配或重定位。因此,如果您的地址空间变得支离破碎,您别无选择,只能释放和重建。

      VirtualAlloc 的主要用例是当您需要编写自己的内存管理器时,例如可以产生巨大影响的 SQL 实现。或者,如果您正在实施即时编译器 (JIT),因为您需要能够将编译到的页面上的保护标志从读/写更改为读/执行,以免触发数据执行保护。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-22
        • 2019-04-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多