我需要使用VirtualAlloc / VirtualAllocEx?

时间:2013-07-07 15:13:29

标签: c++ winapi virtualalloc

我需要使用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]吗?

2 个答案:

答案 0 :(得分:12)

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

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

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

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

答案 1 :(得分:6)

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

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