Для размещения в глобальной динамической памяти следует вызвать функцию GlobaIAUoc(). Интерфейс прикладного программирования (API) Windows объявляет эту функцию следующим образом:
HGLOBAL GlobalAlloc(UINT fuAlloc, DWORD cbAlloc);
fuAlloc — беззнаковое целое, задающее различные опции размещения.
cbAlloc — число байтов, запрашиваемое в глобальной динамической памяти.
GlobalAlloc() возвращает дескриптор (handle) типа HGLOBAL — целое значение, идентифицирующее выделенную память. Если это значение NULL, функция не смогла выделить область требуемого размера. В противном случае можно считать запрос удовлетворенным и блок памяти готовым для использования.
Имеется несколько опций для конфигурации распределенной памяти, многие из которых имели большее значение в ранних версиях Windows, когда не было поддержки виртуальной памяти. Большинство книг по программированию под Windows и систем оперативной подсказки перечисляют все доступные опции, передаваемые как параметры fuAlloc. Однако наилучшим способом размещения динамической структуры является макрос GPTR, представляющий собой комбинацию опций GMEM_FIXED и GMEM_ZEROINT. Эти две опции гарантируют, что блок будет помечен как «фиксированный» (т.е. неперемещаемый) и сразу после распределения обнулен.
Замечание. Поскольку в расширенном режиме Windows использует виртуальную память, «фиксированные» блоки фактически не стоят на одном месте. Windows может перемещать их по памяти или выгружать на диск для удовлетворения последующих запросов на размещение. Слою «фиксированный» означает, что используемый в программе адрес блока не изменится. Несмотря на перемещение блоков по памяти и даже вытеснение их на диск, вы всегда сможете адресовать их.
Важно ясно представлять, что HGLOBAL, возвращаемый Global-АІІосО, не является адресом памяти, а лишь идентификатором, который может быть использован другими функциями для ссылок на выделенный блок. Чтобы получить адрес последнего, нужно вызвать функцию GlobalLock(). Вот пример того, как Windows-программа может распределить и адресовать 2048-байтовый блок:
HGLOBAL hMem;
void FAR* lpBuffer;
hMem = GlobalAlloc(GPTR, 2048);
lpBuffer = GlobalLock(hMem);
if (!lpBuffer) Error();
Первая строка листинга определяет дескриптор hMem типа HGLOBAL для ссылок на выделяемый блок.
Вторая строка определяет дальний указатель типа void, названный lpBuffer, который будет адресовать тот же самый блок.
В третьей строке вызывается Gk>balAlloc() — запрос на 2048 байтов из динамической памяти, используя упоминаемый выше макрос GPTR.
В четвертой строке вызывается функция GlobalLock() с hMem в качестве аргумента, а результат функции присваивается указателю lpBuffer. Наконец, если lpBuffer имеет значение, отличное от NULL, то он адресует выделенный блок. (Не нужно проверять, возвратила ли GlobalAlloc() значение NULL, т.к. если это произошло, Gk>balAIloc() завершится аварийно и проблема будет решена, прежде чем что-то сломается.)