Для чего мне нужно использовать VirtualAlloc/VirtualAllocEx?

Для чего мне нужно использовать VirtualAlloc/VirtualAllocEx?

Пример, один случай, который я обнаружил - если я выделил 4 ГБ виртуальной памяти, то, если я не использую все из них, то я не трачу физическую память, и если я изменяю размер своего массива, мне не нужно делать новый выделение и копирование старых данных в новый массив.

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

Или со стандартным распределителем, я должен потратить 4 ГБ физической памяти:

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 ответа

Решение

Другое использование для VirtualAllocEx который еще не был упомянут, это выделить память в адресном пространстве другого процесса. Обратите внимание, что первым параметром является дескриптор процесса - функция выделяет память в виртуальном адресном пространстве этого процесса.

Я использовал это раньше, когда вводил код в другой процесс, заставляя LoadLibrary позвонить в целевой процесс. Основные шаги заключаются в следующем:

  1. Получить идентификатор процесса целевого процесса (например, с чем-то вроде GetWindowThreadProcessId).
  2. Получить дескриптор процесса с соответствующими разрешениями, используя OpenProcess,
  3. Выделите немного памяти в этом процессе с VirtualAllocEx,
  4. Скопируйте имя вашей DLL в эту память с помощью WriteProcessMemory,
  5. Получить адрес LoadLibrary использовать функцию GetProcAddress,
  6. Вызов CreateRemoteThread чтобы начать LoadLibrary вызов в целевом процессе с параметром потока, являющимся памятью, выделенной для VirtualAllocEx (содержит имя DLL).

Не то чтобы вам нужно было все это знать, но я подумал, что это был интересный пример использования.

VirtualAlloc а также VirtualAllocEx в очень упрощенном виде выделить необработанные страницы, все другие функции памяти из malloc в GlobalAlloc все используют VirtualAllocEx под. Проблема с VirtualAlloc является то, что это в основном сырая память, нет перераспределения или перемещения доступны. Таким образом, если ваше адресное пространство становится фрагментированным, у вас нет другого выхода, кроме как освободить и восстановить.

Основной вариант использования для VirtualAlloc это когда вам нужно написать свой собственный менеджер памяти, скажем, реализацию SQL, где это может иметь огромное значение. Или если вы внедрили компилятор Just In Time (JIT), так как вам нужно было бы иметь возможность изменять флаги защиты на странице, на которую вы компилируете, с чтения / записи на чтение / выполнение, чтобы не запускать предотвращение выполнения данных.

Другие вопросы по тегам