Управление памятью в операционной системе WINDOWS, страница 4

Если использовать VirtualAlloc описанным образом, эта функция выделит участок памяти указанного объема точно так же, как если бы вы использовали для этой цели стандартный вызов malloc. Зачем это может потребоваться? В отличие от malloc функция VirtualAlloc позволяет выделить участок памяти, выровненный по границе страницы, который будет обладать указанными вами атрибутами. Кроме того, в случае необходимости вы сможете корректно освободить этот участок памяти и передать его в ведение операционной системы. Дело в том, что некоторые библиотеки не возвращают освобождаемую память операционной системе.

Если вы хотите изменить уровень защиты для какой-либо одной (или всех) страницы выделенного участка, вы можете воспользоваться вызовом VirtualProtect. При этом участку памяти можно присвоить любой из атрибутов, перечисленных в табл.1. Функция VirtualProtectEx позволяет выполнить ту же процедуру в отношении памяти, которой обладает некоторый процесс. Конечно, в этом случае, программа, обращающаяся к VirtualProtectEx, должна обладать необходимыми привилегиями в отношении целевого процесса. Чтобы освободить память, выделенную при помощи VirtualAlloc, необходимо обратиться к функции VirtualFree.

Но помимо перечисленных функция Virtua1Alloc обладает некоторыми другими весьма полезными возможностями. Если в качестве третьего аргумента функции Virtua1Alloc вместо флага МЕМ_СОММIТ использовать флаг MEM_RESERVE, функция сработает иначе. В этом случае функция Virtua1Alloc резервирует указанный объем линейного адресного пространства, однако реальная физическая или виртуальная память при этом не выделяется. Речь идет лишь о резервировании диапазона адресов.

Когда вы захотите выделить реальную память, соответствующую этим адресам, вы должны обратиться к вызову Virtua1Alloc и передать ему адрес участка памяти и флаг МЕМ_СОММIТ. Выделять память сразу для всего зарезервированного диапазона адресов вовсе не обязательно. Например, можно зарезервировать 10 Мбайт адресного пространства, а затем выделять память из этого диапазона адресов фрагментами по 100 Кбайт.

VirtualAlloc на практике

Чтобы сравнить скорость выполнения функции Virtua1Alloc в различных режимах, запустите программу, исходный код которой приведен в листинге 1. Эта программа получает в индивидуальное пользование относительно большой участок памяти, при этом используются три разных метода. По умолчанию программа работает с блоком памяти объемом 75 Мбайт. Это значение приемлемо для тестирования механизмов выделения/освобождения памяти. Если вы захотите работать с блоком памяти другого размера, его размер (количество мегабайт) можно указать в командной строке при запуске программы.

Листинг 1.

#include <windows.h>

#include <iostream.h>

char *p=NULL;

#define MEGABYTE 1048576

#define MSIZE 75

void main(int argc, char *argv[])

{

char choice;

int msize=0;

if (argc>1) msize=atoi(argv[1]);

if (!msize) msize=MSIZE;

do

{

int valid=1;

if (p)

{

cout<<"\nОсвобождение памяти\n";

VirtualFree(p,0,MEM_RELEASE);

p=NULL;

cout<<"Завершено\n";

}

cout<<"1 - Выделить " <<msize<< "MB памяти\n";

cout<<"2 - Зарезервировать " <<msize<<"MB памяти\n";

cout<<"3 - Зарезервировать " <<msize<<"MB памяти и выделить в ней  1MB\n";

cout<<"4 - Выход\n";

cout<<"Ваш выбор: ";

cin>>choice;

switch (choice)

{

case '1':

cout<<"\nВыделение памяти\n";

p=(char *)VirtualAlloc(NULL, msize*MEGABYTE,

MEM_COMMIT,PAGE_READWRITE);

break;

case '2':

cout<<"\nРезервирование памяти\n";

p=(char *)VirtualAlloc(NULL, msize*MEGABYTE,

MEM_RESERVE, PAGE_READWRITE);

break;

case '3':

cout<<"\nРезервирование и частичное выделение памяти\n";

p=(char *)VirtualAlloc(NULL, msize*MEGABYTE,

MEM_RESERVE, PAGE_READWRITE);

cout<<"\nВыделение\n";