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

В качестве первого аргумента можно указать комбинацию из двух флагов: HEAP_GENERATE_EXCEPTIONS, который предписывает Windows генерировать исключение в случае, если вызов окончился неудачей (если этот флаг сброшен, в случае неудачи вызов HeapCreate возвращает значение NULL), и HEAP_NO_SERIALIZE, который предписывает Windows не осуществлять слежение за одновременным доступом к куче нескольких потоков (если этот флаг сброшен, Windows автоматически блокирует одновременный доступ к куче нескольких потоков, благодаря чему потоки обращаются к куче по очереди). Значения этих флагов можно установить как при обращении к HeapCreate, так и при обращении к другим вызовам, обслуживающим кучу.                                                       

Второй аргумент содержит начальный размер кучи. Система округляет это значение таким образом, чтобы оно соответствовало целому количеству страниц! На компьютерах архитектуры Infel размер страницы составляет 4 Кбайт, таким образом, если вы захотите создать кучу объемом 4000 байт, реально будет создана куча объемом 4096 байт. Вы можете узнать размер страницы при помощи вызова GetSystemInfo.                                                     

Третий аргумент вызова — HeapCreate — это максимальный допустимый размер кучи. Это значение также округляется таким образом, чтобы оно соответствовало целому количеству страниц, Чаще всего в качестве максимального размера кучи указывают значение 0. В этом случае размер кучи не ограничивается. Если размер кучи ограничен, в этой куче за одну операцию можно выделить участок памяти, размер которого не может превышать 0x7FFF8 байтов. При этом HeapCreate зарезервирует (но не выделит) адресное пространство, соответствующее максимальному размеру кучи. Если размер кучи не ограничен, куча будет расти до тех пор, пока хватит виртуального адресного пространства. В этом случае количество байт, которые допускается выделить за одну операцию, ничем не ограничивается.

Если вы намерены ограничить максимальный размер кучи, имейте в виду, что система использует некоторое количество памяти для управления кучей. Это значит, что в куче размером 64 Кбайт для вашей программы будет доступно несколько меньшее количество памяти.

Если куча больше не нужна, вы должны уничтожить ее при помощи вызова HeapDestroy,

Куча по умолчанию

Каждая программа обладает кучей по умолчанию. Если вы хотите получить дескриптор этой кучи, воспользуйтесь вызовом GetProcessHeap. Вызывать функцию HeapDestroy для этого дескриптора нельзя.

Выделение и освобождение памяти в куче

Обладая дескриптором кучи, вы можете использовать вызов НеарAllос для того, чтобы выделить память в этой куче. Этой функции необходимо передать дескриптор кучи, аргумент с флагами и размер в байтах выделяемого участка. Флаги могут быть следующими: HEAP_GENERATE_EXCEPTIONS, HEAP_NO_SERIALIZE или НЕАР_ ZERO_MEMORY, Первые два флага имеют такое же значение, как и при обращении к HeapCreate. Флаг HEAP_ZERO_MEMORY предписывает Windows обнулить значение выделяемых ячеек памяти перед тем, как управление будет возвращено вызвавшей программе.

Помните, что, если куча имеет фиксированный размер, нельзя выделить участок памяти, размер которого превышает 0x7FFF8 байт. Выделив участок памяти, вы можете узнать его реальный размер (который может превышать указанное вами значение) при помощи вызова HeapSize.

Изменить размер ранее выделенного участка можно при помощи вызова HeapReAltoc. Помимо уже известных вам флагов HEAP_GENERATE_EXCEPTIONS, HEAP_NO_ SERIALIZE или HEAP_ZERO_MEMORY, можно использовать флаг HEAP_REALLOC_IN_PLACE_ONLY, который указывает на то, что процедура изменения размера участка должна завершиться неудачей в случае, если для изменения размера участка требуется перемещение этого участка в другую область памяти. Такая ситуация может возникнуть в случае, если вы увеличиваете размер участка памяти. Уменьшение размера участка никогда не требует его перемещения.

Чтобы освободить ранее выделенный участок памяти, следует обратиться к функции HeapFree. Чтобы предотвратить сериализацию памяти, следует использовать флаг HEAP_NO_SERIALIZE.