2013-07-07 137 views
3

为了什么我需要使用VirtualAlloc/VirtualAllocEx?我需要什么来使用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 

或用standatd分配器,我必须花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]带来的好处?

回答

11

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

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

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

不是你需要知道所有这些,但我虽然是一个有趣的用例。

5

VirtualAlloc和非常简单的术语VirtualAllocEx分配生的网页,与所有其他存储功能从mallocGlobalAlloc都使用VirtualAllocEx下方。 VirtualAlloc的问题在于它基本上是原始记忆,没有可用的重新分配或重新定位。因此,如果你的地址空间变得分散,你就没有办法,只能释放和重建。

主要用例VirtualAlloc是当你需要编写自己的内存管理器,用于说SQL实现在那里可以产生巨大的变化。或者,如果您正在实施即时编译器(JIT),则需要能够将您编译的页面上的保护标志从读/写更改为读/执行,以不触发Data Execution Prevention。

相关问题