简体   繁体   English

我需要使用VirtualAlloc / VirtualAllocEx?

[英]For what do I need to use VirtualAlloc/VirtualAllocEx?

For what do I need to use VirtualAlloc/VirtualAllocEx? 我需要使用VirtualAlloc / VirtualAllocEx?

An example, one case that I found - if I allocated 4 GB of virtual memory, then if I do not use all of them, then I do not spend physical memory, and if I resize my array, I do not need to do new allocating and copying old data to new array. 一个例子,我发现的一个案例 - 如果我分配了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)

And if I used standard allocator, I need to copy of data when I do resize: 如果我使用标准分配器,我需要在调整大小时复制数据

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

Or with standatd allocator, I must spend 4GB of physical memory: 或者使用标准分配器,我必须花费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

But, why this is better than realloc()? 但是,为什么这比realloc()更好? http://www.cplusplus.com/reference/cstdlib/realloc/ http://www.cplusplus.com/reference/cstdlib/realloc/

And are there any else cases to use VirtualAlloc[Ex] with benefits? 还有其他案例使用VirtualAlloc [Ex]带来好处吗?

Another use for VirtualAllocEx which hasn't been mentioned yet, is to allocate memory in another process' address space. VirtualAllocEx另一个用途(尚未提及)是在另一个进程的地址空间中分配内存。 Note that the first parameter is the handle to a process - the function allocates the memory within the virtual address space of that process. 请注意,第一个参数是进程的句柄 - 该函数在该进程的虚拟地址空间内分配内存。

I've used this before when injecting code into another process, by forcing a LoadLibrary call in the target process. 我之前通过在目标进程中强制执行LoadLibrary调用将代码注入到另一个进程中时使用过它。 The basic steps are as follows: 基本步骤如下:

  1. Get the process id of the target process (eg with something like GetWindowThreadProcessId ). 获取目标进程的进程ID(例如,使用类似GetWindowThreadProcessId进程)。
  2. Get a handle to the process with the appropriate permissions using OpenProcess . 使用OpenProcess以适当的权限获取进程的句柄。
  3. Allocate some memory in that process with VirtualAllocEx . 使用VirtualAllocEx在该过程中分配一些内存。
  4. Copy the name of your DLL into that memory with WriteProcessMemory . 使用WriteProcessMemory将DLL的名称复制到该内存中。
  5. Get the address of the LoadLibrary function using GetProcAddress . 使用GetProcAddress获取LoadLibrary函数的地址。
  6. Call CreateRemoteThread to start the LoadLibrary call in the target process, with the thread parameter being the memory you've allocated with VirtualAllocEx (containing the name of the DLL). 调用CreateRemoteThread以在目标进程中启动LoadLibrary调用,其中thread参数是您使用VirtualAllocEx (包含DLL的名称)分配的内存。

Not that you needed to know all of that, but I though it was an interesting use case. 并不是说你需要了解所有这些,但我认为这是一个有趣的用例。

VirtualAlloc and VirtualAllocEx in very simplistic terms allocate raw pages, all other memory functions from malloc to GlobalAlloc all use VirtualAllocEx underneath. VirtualAllocVirtualAllocEx以非常简单的术语分配原始页面,从mallocGlobalAlloc所有其他内存函数都使用VirtualAllocEx The problem with VirtualAlloc is that it is basically raw memory, there is no reallocation or relocation available. VirtualAlloc的问题在于它基本上是原始内存,没有可用的重新分配或重定位。 As such if your address space becomes fragmented you have no recourse but to release and rebuild. 因此,如果您的地址空间变得支离破碎,您无需追索,只能释放和重建。

The primary use case for VirtualAlloc is when you need to write your own memory manager, for say a SQL implementation where it can make a huge difference. VirtualAlloc的主要用例是当您需要编写自己的内存管理器时,例如SQL实现,它可以产生巨大的差异。 Or if you were implementing a Just In Time Compiler (JIT), as you would need to be able to change the protection flags on the page you compile into from read/write to read/execute as to not trigger Data Execution Prevention. 或者,如果您正在实现即时编译器(JIT),那么您需要能够将编译的页面上的保护标志从读/写更改为读/执行,以便不触发数据执行保护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM