2013-07-07 4 views
3

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

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

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 распределителем, я должен потратить 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] с выгодами?

ответ

11

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

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

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

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

5

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

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

Смежные вопросы