Что такое код globalalloc


Содержание

Что такое код globalalloc

Выделяет указанное количество байт из кучи

#include
_MemGlobalAlloc ( $iBytes [, $iFlags = 0 ])

$iBytes Количество байт, которое будет выделено. Если этот параметр равен нулю, а параметр $iFlags равен $GMEM_MOVEABLE , то функция возвращает дескриптор объекта памяти, который помечен как сброшенный.
$iFlags [необязательный] Атрибуты выделенной памяти:
$GMEM_FIXED — Выделяет фиксированную память. Возвращает указатель.
$GMEM_MOVEABLE — Выделяет доступную для перемещения память. Блоки памяти никогда не перемещаются в физическую память, но они могут быть перемещены в пределах кучи по умолчанию. Возвращаемое значение является дескриптором объекта памяти.
Чтобы преобразовывать дескриптор в указатель, используйте функцию _MemGlobalLock. Это значение не может быть объединено с $GMEM_FIXED .
$GMEM_ZEROINIT — Инициализирует память заполняя содержимое в 0
$GHND — Объединяет в себе $GMEM_MOVEABLE и $GMEM_ZEROINIT
$GPTR — Объединяет в себе $GMEM_FIXED и $GMEM_ZEROINIT
Успех: Возвращает дескриптор объекта выделенной памяти
Ошибка: Возвращает 0

Windows memory management does not prov >$PAGE_EXECUTE access. Чтобы освободить память, используйте функцию _MemGlobalFree.

Что такое код globalalloc

( В линейках ОС Windows NT и 9x не используется )

Функция GlobalLock возвращает указатель на данный объект памяти глобальных данных. Функция GlobalLock наращивает(увеличивает на единицу) счетчик блокировки перемещаемых объектов и фиксирует память. Фиксированная память не будет перемещаться или сбрасывается до тех пор, пока объект памяти не будет перераспределен функцией GlobalReAlloc. Объект остается блокированным (фиксированным) в памяти до тех пор, пока счетчик блокировки не уменьшится до нуля.

Синтаксис

Параметры

Идентификатор объекта памяти глобальных данных, которые фиксируются.

Возвращаемые значения

Возвращаемое значение указывает на первый байт памяти в глобальном объекте, если функция завершается успешно. Оно — NULL, если память объекта была сброшена, или произошла ошибка.

Замечания

Каждый раз, когда приложение вызывает функцию GlobalLock для объекта, оно должно в конечном счете вызвать и функцию GlobalUnlock для этого объекта.

Эта функция возвратит NULL, если приложение попытается зафиксировать объект памяти размером нуль байтов.

Если функция GlobalLock увеличивает счетчик блокировки объекта, то функция GlobalUnlock уменьшает на 1 счетчик блокировки (фиксации) объекта. Другие функции могут также оказать влияние на подсчет блокировок объекта памяти. Список этих функций, см. в описании функции GetGlobalFlags.

У объектов со сброшенными данными счетчик блокировки (фиксации) всегда равен нулю.

Пример

В нижеследующем примере используются функции GlobalAlloc и GlobalLock, чтобы назначить память, а затем вызываются функции GlobalUnlock и GlobalFree, чтобы освободить ее.

Операционная система Microsoft Windows 3.1 для программиста

2.3. Работа с памятью в приложениях Windows

В этом разделе мы расскажем вам о типах памяти, используемых приложениями Windows и о том, как приложения могут заказать для себя память.

Глобальная динамическая память

В Windows версии 3.1 область глобальной памяти общая для всех приложений Windows. Теоретически одно приложение может заказать для себя блок памяти из глобальной области и передать его идентификатор другому приложению, однако такая практика не приветствуется, так как в следующих версиях Windows адресные пространства приложений могут быть разделены (для передачи данных между приложениями необходимо использовать механизм динамической передачи данных DDE, который будет описан в одном из следующих томов «Библиотеки системного программиста»).

Получение глобального блока памяти

Для получения глобального блока памяти вы должны использовать функцию GlobalAlloc :

Параметр fuAlloc определяет тип выделяемой памяти. Размер блока памяти в байтах должен передаваться через параметр cbAlloc, причем вы можете заказать блок памяти размером больше, чем 64 Кбайт. Для стандартного режима работы Windows можно заказать блок памяти размером до 1 Мбайт без 80 байт, для расширенного — до 16 Мбайт без 64 Кбайт.

Функция возвращает идентификатор глобального блока памяти или NULL, если Windows не может выделить память указанного объема.

Параметра fuAlloc должен быть указан как логическая комбинация следующих значений:

Флаг Описание
GMEM_DDESHARE Блок памяти будет использоваться совместно несколькими приложениями при помощи механизма динамического обмена данными DDE
GMEM_DISCARDABLE Заказывается удаляемый блок памяти. Этот флаг должен использоваться совместно с флагом GMEM_MOVEABLE
GMEM_FIXED Заказывается фиксированный блок памяти. Этот флаг несовместим с флагом GMEM_MOVEABLE.При работе в среде Windows версии 3.1 в защищенном режиме фиксированный сегмент, созданный с использованием флага GMEM_FIXED, является перемещаемым. Для такого сегмента в процессе перемещения логический адрес не изменяется, но линейный (и, следовательно, физический) может изменяться
GMEM_LOWER Синоним для GMEM_NOT_BANKED. Не используется в Windows версии 3.1
GMEM_MOVEABLE Заказывается перемещаемый блок памяти. Логический адрес перемещаемого блока памяти может изменяться. Этот флаг несовместим с флагом GMEM_FIXED
GMEM_NOCOMPACT Для удовлетворения запроса памяти не следует выполнять объединение всех свободных участков памяти в один и удалять блоки памяти, отмеченные как удаляемые
GMEM_NODISCARD Для удовлетворения запроса памяти не следует выполнять объединение всех свободных участков памяти в один
GMEM_NOT_BANKED Получить блок памяти вне фрейма дополнительной памяти EMS. Не используется в Windows версии 3.1
GMEM_NOTIFY Если заказанный объект будет удален, требуется вызов процедуры извещения. Процедура извещения назначается функцией GlobalNotify и должна располагаться в фиксированном сегменте кода в библиотеке DLL. С ее помощью приложение может разрешить или запретить Windows удалять блок данных
GMEM_SHARE Синоним для GMEM_DDESHARE
GMEM_ZEROINIT Во все байты блока необходимо записать нулевые значения
GHDN Синоним для комбинации флагов GMEM_MOVEABLE и GMEM_ZEROINIT
GPTR Синоним для комбинации флагов GMEM_FIXED и GMEM_ZEROINIT

Идентификатор, полученный от функции GlobalAlloc, нельзя использовать для адресации памяти непосредственно. Напомним, что пока вы не зафиксировали блок памяти, его логический адрес недоступен.

Приведем для примера фрагмент кода, в котором мы получаем перемещаемый блок памяти размером 200000 байт, причем во все байты полученного блока записываются нулевые значения:

В следующем фрагменте мы заказываем удаляемый блок памяти размером 200000 байт, который никак не инициализируется:

Фиксирование и расфиксирование блока памяти

Для получения доступа к полученному блоку памяти его необходимо зафиксировать, вызвав функцию GlobalLock :

Функция GlobalLock фиксирует блок памяти, идентификатор которого передается ей через параметр hglb и возвращает логический адрес зафиксированного блока или NULL, если указанный блок удален или произошла ошибка.

В защищенном режиме работы Windows продолжает перемещать блоки памяти, зафиксированные функцией GlobalLock, изменяя базовый адрес в локальной таблице дескрипторов. Даже для фиксированных блоков памяти вызов этой функции все же необходим, потому что нужно получить логический адрес блока памяти.

Для каждого блока памяти Windows поддерживает счетчик фиксирований. Этот счетчик увеличивается при вызове функции GlobalLock и уменьшается при расфиксировании блока функцией GlobalUnlock :

Если содержимое счетчика уменьшилось до нуля, функция возвращает значение FALSE. В противном случае возвращается TRUE.

Файл windowsx.h содержит макрокоманды, облегчающие работу с глобальными блоками памяти. Например, макрокоманда GlobalAllocPtr получает блок памяти и фиксирует его:

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

Определение идентификатора блока памяти по его адресу

С помощью функции GlobalHandle вы можете, зная селектор блока памяти, определить его идентификатор:

Параметр uGlobalSel указывает селекторную компоненту логического адреса блока памяти.

Младшее слово возвращаемого значения содержит идентификатор блока памяти, старшее — селектор блока памяти. В случае ошибки возвращается нулевое значение.

В файле windowsx.h определена макрокоманда GlobalPtrHandle , упрощающая получение идентификатора блока памяти по его логическому адресу:

Макрокоманда SELECTOROF определена в файле windows.h и предназначена для получения селекторной компоненты логического адреса:

В файле windows.h есть также определения для макрокоманды OFFSETOF , возвращающей компоненту смещения, и макрокоманда MAKELP , конструирующая указатель из компонент смещения и селектора:

Если вы работаете с транслятором Borland C++ for Windows, вместо этих макрокоманд можете использовать знакомые вам макрокоманды FP_SEG , FP_OFF и MK_FP , описанные в файле dos.h:

Работа с удаляемыми блоками памяти

Для того чтобы заказать удаляемый блок памяти, вы должны указать флаги GMEM_DISCARDABLE и GMEM_MOVEABLE , например:

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

При попытке зафиксировать удаленный блок с помощью функции GlobalLock приложение получит от этой функции значение NULL. В этом случае следует вызвать функцию GlobalFlags , предназначенную для определения состояния блока памяти, и проверить, находится ли данный блок в удаленном состоянии.

Приведем прототип функции GlobalFlags:

Функция возвращает состояние блока памяти, указанного своим единственным параметром. Младший байт возвращаемого значения содержит содержимое счетчика фиксаций блока памяти. В старшем байте могут быть установлены флаги GMEM_DISCARDABLE и GMEM_DISCARDED.

Если установлен флаг GMEM_DISCARDABLE, проверяемый блок памяти может быть удален Windows в процессе дефрагментации свободной области памяти. Если же установлен флаг GMEM_DISCARDED, удаление блока памяти уже произошло.

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

Приведем прототип функции GlobalReAlloc :

Параметр hglb указывает идентификатор восстанавливаемого блока памяти.

При помощи параметра cbNewSize вы должны указать размер блока памяти, причем можно восстановить удаленный блок памяти и изменить его размер одновременно.

Параметр fuAlloc определяет тип восстановленного блока памяти. Можно указывать логическую комбинацию следующих флагов:

Флаг Описание
GMEM_DISCARDABLE Если блок памяти был перемещаемый, то теперь дополнительно он будет и удаляемый. Этот флаг должен использоваться совместно с флагом GMEM_MODIFY
GMEM_MODIFY Выполняется изменение характеристик существующего блока памяти. этот флаг необходимо указывать вместе с флагами GMEM_DISCARDABLE и GMEM_MOVEABLE
GMEM_MOVEABLE Если раньше указанный блок памяти был перемещаемым и удаляемым, содержимое счетчика фиксирования для него равно нулю и новый размер блока указан равным нулю, данный блок будет удален. Если же параметр cbNewSize равен нулю, но блок памяти не является перемещаемым или удаляемым, функция вернет признак ошибки.Для фиксированного блока памяти ненулевой длины данный флаг разрешает перемещение, т. е. преобразует фиксированный блок в перемещаемый.
GMEM_NODISCARD Блок памяти не может быть удален операционной системой. Этот флаг должен использоваться совместно с флагом GMEM_MODIFY
GMEM_ZEROINIT Если размер блока памяти увеличивается, во все байты дополнительной памяти необходимо записать нулевые значения. Этот флаг несовместим с флагом GMEM_MODIFY

Восстановив блок памяти, вы должны зафиксировать его функцией GlobalLock и затем восстановить прежнее содержимое, так как после удаления от блока остался только идентификатор.

Изменение блока памяти

Как мы уже говорили, функция GlobalReAlloc , описанная выше, позволяет изменить характеристики глобального блока памяти.

Если вам, например, надо изменить размер заказанного ранее блока памяти, сделав его равным 51200 байт, вы можете для этого использовать следующий фрагмент кода:

После вызова функции блок памяти будет перемещаемый и удаляемый, причем если раньше его размер был меньше 51200 байт, во все байты дополнительной памяти будут записаны нулевые значения.

Учтите, что при увеличении размера блока может возникнуть ситуация нехватки памяти, поэтому проверяйте значение идентификатора, возвращаемой функцией GlobalReAlloc, на неравенство константе NULL.

Вы можете инициировать удаление блока памяти при помощи функции GlobalReAlloc, если укажите нулевой размер блока и флаг GMEM_MOVEABLE. В файле windows.h имеется определение макрокоманды GlobalDiscard, при помощи которой приложение может принудительно удалить блок из памяти:

Илон Маск рекомендует:  Работа с реестром

Определение размера блока памяти

С помощью функции GlobalSize вы можете определить размер блока памяти по его идентификатору:

Эта функция возвращает размер блока памяти, идентификатор которого задан параметром hglb. Если указанный блок памяти не существует или удален, возвращается нулевое значение.

Дефрагментация памяти

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

Функция возвращает размер самого большого доступного непрерывного блока памяти, причем, если параметр на равен 0 или -1, выполняется дефрагментация памяти и удаление блоков, отмеченных как удаляемые. Если параметр функции указан как 0 или -1, функция не выполняет дефрагментацию памяти, но возвращает правильное значение с учетом возможного выполнения дефрагментации.

Получение памяти в первом мегабайте адресного пространства

Если у вас возникает необходимость заказать память, доступную приложениям MS-DOS, и располагающуюся в первом мегабайте адресного пространства, воспользуйтесь функцией GlobalDosAlloc :

Параметр cbAlloc определяет размер блока в байтах.

Старшее слово возвращаемого значения содержит сегментную компоненту адреса реального режима, соответствующего полученному блоку памяти. Это значение может использоваться для доступа к блоку памяти в реальном режиме работы процессора.

Младшее слово возвращаемого значения содержит селектор для доступа к полученному блоку в защищенном режиме.

Память, заказанная при помощи функции GlobalDOSAlloc, является фиксированной, поэтому вам не следует вызывать функцию GlobalLock для фиксирования и получения логического адреса.

Для освобождения блока памяти, полученного при помощи функции GlobalDOSAlloc, следует вызвать функцию GlobalDosFree :

В качестве параметра uSelector этой функции следует передать селекторную компоненту блока памяти, расположенного в первом мегабайте адресного пространства.

В случае успешного завершения возвращаемое значение равно нулю. При ошибке возвращается селектор, указанный в параметре uSelector.

Учтите, что заказывать памяти в первом мегабайте можно только в случае крайней необходимости, когда, вам, например, нужно обеспечить одновременный доступ к памяти со стороны приложений Windows и программ MS-DOS. Уменьшение свободного пространства в первом мегабайте адресного пространства отрицательно сказывается на производительности работы приложений Windows.

Освобождение глобального блока памяти

Для освобождения глобального блока памяти, полученного от функции GlobalAlloc, вы должны использовать функцию GlobalFree :

Идентификатор освобождаемого блока передается функции в качестве ее единственного параметра.

Функция возвращает NULL при успешном завершении или значение hglb при ошибке.

Перед освобождением зафиксированных блоков памяти их следует предварительно расфиксировать. Вы можете узнать содержимое счетчика фиксаций блока при помощи функции GlobalFlags, описанной выше.

Для освобождения памяти, полученной при помощи макрокоманды GlobalAllocPtr, удобно использовать макрокоманду GlobalFreePtr , описанную в файле windowsx.h:

Данная макрокоманда расфиксирует, а затем и освобождает блок памяти, заданный своим логическим адресом.

Фиксирование линейного адреса блока памяти

В некоторых случаях вам необходимо запретить изменение линейного адреса блока памяти, которое выполняется в процессе перемещения. Такое изменение выполняется заменой базового адреса в соответствующем дескрипторе локальной таблицы дескрипторов. В результате при перемещении блока логический адрес остается постоянным (так как при перемещении блока ему не присваивается новый дескриптор, а логический адрес состоит из ссылки на дескриптор, номера запрошенного кольца защиты и смещения), в то время как линейный может изменяться.

Если драйвер какого-либо устройства ввода/вывода работает с линейным адресом буфера, память, отведенная для такого буфера в некоторых случаях должна быть зафиксирована функцией GlobalFix :

Параметр функции указывает идентификатор фиксируемого блока памяти.

Как только отпадет необходимость в фиксировании блока памяти, его следует расфиксировать, вызвав функцию GlobalUnfix :

Единственный параметр этой функции должен содержать идентификатор блока памяти, который будет расфиксирован.

Фиксирование страниц блока памяти

В расширенном режиме работы операционной системы Windows версии 3.1 используется виртуальная память. Как мы уже говорили, при использовании виртуальной памяти вся глобальная область памяти делится на страницы размером 4 Кбайт. Эти страницы могут располагаться в физической оперативной памяти или на диске в специальном файле виртуальной памяти. Если приложение обращается к странице, которая отсутствует в физической оперативной памяти, она загружается туда из файла виртуальной памяти.

Однако на загрузку страницы памяти из файла требуется значительное время. В некоторых случаях необходимо обеспечить постоянное присутствие блока памяти в физической оперативной памяти.

Фиксирование блока памяти функцией GlobalFix не предотвращает сброс страниц памяти, распределенных блоку, в файл виртуальной памяти, а всего лишь запрещает перемещение блока памяти в линейном адресном пространстве.

Для исключения страниц памяти, принадлежащих указанному блоку памяти, из процесса страничного обмена необходимо использовать функцию GlobalPageLock :

Идентификатор блока, для которого необходимо запретить страничный обмен, указывается через параметр hglb.

Операционная система Windows поддерживает счетчик блокирования страничного обмена. Содержимое этого счетчика увеличивается на единицу при каждом вызове функции GlobalPageLock.

Функция GlobalPageLock возвращает новое значение счетчика или ноль при ошибке.

Как только надобность в блокировке страничного обмена отпадает, следует вызвать функцию GlobalPageUnlock :

Эта функция разрешает страничный обмен для блока памяти, заданного параметром hglb. Функция возвращает текущее значение счетчика или ноль при ошибке.

Приложение GMEM

Для демонстрации использования основных функций управления глобальной памятью мы приведем исходный текст приложения GMEM (листинг 2.3).

Листинг 2.3. Файл gmem/gmem.cpp

Перед началом работы приложение определяет объем свободной памяти, вызывая функцию GlobalCompact со значением параметра, равным -1. Определенное значение выводится на экран при помощи функции MessageBox.

Далее приложение вызывает функцию GlobalCompact еще раз для освобождения непрерывного блока свободной памяти размером 100000 байт.

После этого приложение заказывает буфер размером 100000 байт, вызывая функцию GlobalAlloc. В качестве первого параметра этой функции указана константа GHND, соответствующее перемещаемой памяти, инициализированной нулевым значением.

В случае успешного получения блока памяти он фиксируется и на экран выводится значение идентификатора блока и его логический адрес. После этого в первый байт полученного блока записывается код символа ‘S’ и блок расфиксируется. При ошибке выдается сообщение.

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

После этого приложение заказывает удаляемый блок памяти размером 200000 байт и сразу же удаляет его, вызывая макрокоманду GlobalDiscard. Затем приложение предпринимает попытку зафиксировать только что удаленный блок памяти, вызывая функцию GlobalLock. Если блок памяти удалился успешно, функция GlobalLock должна вернуть значение NULL. В этом случае нам надо убедиться в том, что блок был удален, и если это так и есть, восстановить удаленный блок.

Для проверки приложение использует функцию GlobalFlags. Если блок, идентификатор которого был передан этой функции в качестве параметра, удален, в возвращаемом значении установлен флаг GMEM_DISCARDED.

Для восстановления удаленного блока приложение вызывает функцию GlobalReAlloc, указывая размер и характеристики блока. Затем восстановленный блок фиксируется в памяти и на экран выводится его идентификатор и логический адрес.

Перед завершением работы приложения блок расфиксируется и освобождается.

Файл определения модуля приложения GMEM приведен в листинге 2.4.

Листинг 2.4. Файл gmem/gmem.def

Локальная динамическая память

Для каждого приложения Windows создается автоматический сегмент данных размером 64 Кбайт, в котором располагаются статические данные , стек и локальная область данных (local heap ). Кроме этого, автоматический сегмент данных имеет заголовок размером 16 байт (рис. 2.10).

Рис. 2.10. Автоматический сегмент данных приложения Windows

Размер стека определяется оператором STACKSIZE в файле определения модуля:

Минимальный размер стека, назначаемый Windows для приложений, составляет 5 Кбайт. Следует отметить, что в руководстве к SDK нет точного описания способа определения минимально необходимого объема стека. В этом руководстве предлагается определить этот объем экспериментально, причем подчеркивается, что результаты переполнения стека непредсказуемы.

В отличие от стека, размер локальной области данных может при необходимости увеличиваться автоматически. Начальное значение задается в файле определения модуля при помощи оператора HEAPSIZE :

Вы можете указать любое отличное от нуля значение.

Для работы с локальной областью данных программный интерфейс Windows содержит функции, аналогичные предназначенным для работы с глобальной областью данных.

Получение локального блока памяти

Для получения локального блока памяти вы должны использовать функцию LocalAlloc :

Параметр fuAlloc определяет тип выделяемой памяти. Размер блока памяти в байтах должен передаваться через параметр cbAlloc.

Функция возвращает идентификатор локального блока памяти или NULL, если Windows не может выделить память указанного объема.

Параметра fuAlloc должен быть указан как логическая комбинация следующих значений:

Флаг Описание
LMEM_DISCARDABLE Заказывается удаляемый блок памяти. Этот флаг должен использоваться совместно с флагом LMEM_MOVEABLE
LMEM_FIXED Заказывается фиксированный блок памяти (в защищенном режиме работы блок памяти будет перемещаемым, даже если он заказан с использованием флага LMEM_FIXED, однако в процессе перемещения будет изменяться только линейный адрес, но не логический). Этот флаг несовместим с флагом LMEM_MOVEABLE
LMEM_MOVEABLE Заказывается перемещаемый блок памяти. Логический адрес такого блока может изменяться в процессе перемещения. Этот флаг несовместим с флагом LMEM_FIXED
LMEM_NOCOMPACT Для удовлетворения запроса памяти не следует выполнять объединение всех свободных участков памяти в один и удалять блоки памяти, отмеченные как удаляемые
LMEM_NODISCARD Для удовлетворения запроса памяти не следует выполнять объединение всех свободных участков памяти в один
LMEM_ZEROINIT Во все байты блока необходимо записать нулевые значения
NONZEROLHND Синоним для LMEM_MOVEABLE
NONZEROLPTR Синоним для LMEM_FIXED
LHDN Синоним для комбинации флагов LMEM_MOVEABLE и LMEM_ZEROINIT
LPTR Синоним для комбинации флагов LMEM_FIXED и LMEM_ZEROINIT

Приведем фрагмент кода, в котором мы получаем из локальной области памяти перемещаемый блок размером 2000 байт, причем во все байты полученного блока записываются нулевые значения:

В следующем фрагменте мы заказываем удаляемый блок памяти размером 200 байт, который никак не инициализируется:

Фиксирование и расфиксирование блока памяти

Для получения доступа к полученному блоку памяти его необходимо зафиксировать, вызвав функцию LocalLock :

Функция LocalLock фиксирует блок памяти, идентификатор которого передается ей через параметр hloc и возвращает логический адрес зафиксированного блока или NULL, если указанный блок удален или произошла ошибка.

Так как операционная система Windows версии 3.1 работает только в защищенном режиме, все блоки памяти, зафиксированные при помощи функции LocalLock, будут перемещаемыми. Перемещение блоков памяти выполняется методом изменения базового адреса в локальной таблице дескрипторов, причем логический адрес перемещаемого блока остается неизменным. Поэтому перемещение фиксированных блоков памяти происходит для приложений незаметно.

Для каждого блока памяти Windows поддерживает счетчик фиксирования. Этот счетчик увеличивается при вызове функции LocalLock и уменьшается при расфиксировании блока функцией LocalUnlock :

Если содержимое счетчика уменьшилось до нуля, функция возвращает значение FALSE. В противном случае возвращается TRUE.

Определение идентификатора блока памяти по его адресу

С помощью функции LocalHandle вы можете определить идентификатор локального блока памяти:

Параметр pvMem указывает адрес локального блока памяти.

Возвращаемое значение содержит идентификатор локального блока памяти. В случае ошибки возвращается нулевое значение.

Работа с удаляемыми блоками памяти

Для получения доступа к удаленному локальному блоку памяти его необходимо восстановить, вызвав функцию LocalReAlloc. Эта функция аналогична функции GlobalReAlloc и позволяет изменить характеристики существующего блока памяти.

Приведем прототип функции LocalReAlloc :

Параметр hloc указывает идентификатор восстанавливаемого блока памяти.

При помощи параметра cbNewSize вы должны указать размер блока памяти, причем можно восстановить удаленный блок памяти и изменить его размер одновременно.

Параметр fuAlloc определяет тип восстановленного блок памяти. Можно указывать логическую комбинацию следующих флагов:

Флаг Описание
LMEM_DISCARDABLE Если блок памяти был перемещаемый, то теперь дополнительно он будет и удаляемый. Этот флаг должен использоваться совместно с флагом LMEM_MODIFY
LMEM_MODIFY Выполняется изменение характеристик существующего блока памяти. этот флаг необходимо указывать вместе с флагами LMEM_DISCARDABLE и LMEM_MOVEABLE
LMEM_MOVEABLE Если раньше указанный блок памяти был перемещаемым и удаляемым, содержимое счетчика фиксирования для него равно нулю и новый размер блока указан равным нулю, данный блок будет удален. Если же параметр cbNewSize равен нулю, но блок памяти не является перемещаемым или удаляемым, функция вернет признак ошибки.Для фиксированного блока памяти ненулевой длины данный флаг разрешает перемещение, т. е. преобразует фиксированный блок в перемещаемый.
LMEM_NODISCARD Блок памяти не может быть удален операционной системой. Этот флаг должен использоваться совместно с флагом LMEM_MODIFY
LMEM_ZEROINIT Если размер блока памяти увеличивается, во все байты дополнительной памяти необходимо записать нулевые значения. Этот флаг несовместим с флагом LMEM_MODIFY

Восстановив блок памяти, вы должны зафиксировать его функцией LocalLock и затем восстановить его прежнее содержимое.

Определение характеристик локального блока памяти

Для определения характеристик локального блока памяти предназначена функция LocalFlags , аналогичная рассмотренной нами ранее функции GlobalFlags:

Функция возвращает состояние блока памяти, указанного своим единственным параметром. Младший байт возвращаемого значения содержит содержимое счетчика фиксаций блока памяти. В старшем байте могут быть установлены флаги LMEM_DISCARDABLE и LMEM_DISCARDED.

Илон Маск рекомендует:  Что такое код msql_pconnect

Если установлен флаг LMEM_DISCARDABLE, проверяемый блок памяти может быть удален Windows в процессе дефрагментации свободной области памяти. Если же установлен флаг LMEM_DISCARDED, удаление блока памяти уже произошло.

Определение размера блока памяти

С помощью функции LocalSize вы можете определить размер блока памяти по его идентификатору:

Эта функция возвращает размер блока памяти, идентификатор которого задан параметром hloc. Если указанный блок памяти не существует или удален, возвращается нулевое значение.

Дефрагментация локального блока памяти

Функция LocalCompact выполняет дефрагментацию свободного пространства в локальной области данных:

Функция возвращает размер самого большого доступного непрерывного блока в локальной области памяти, причем, если параметр на равен 0 или -1, выполняется дефрагментация памяти и удаление блоков, отмеченных как удаляемые. Если параметр функции указан как 0, функция не выполняет дефрагментацию памяти, но возвращает правильное значение с учетом возможного выполнения дефрагментации.

Уменьшение размера локального блока памяти

Для уменьшения размера существующего локального блока памяти можно использовать функцию LocalShrink :

Параметр hloc указывает идентификатор изменяемого локального блока памяти. Новые размеры блока памяти задаются параметром cbNewSize.

Возвращаемое значение в случае успеха равно новому размеру блока памяти.

В процессе получения памяти при помощи функции LocalAlloc размер использованной локальной памяти будет расти, пока не достигнет 64 Кбайт. После освобождения локальных блоков данных размер локальной области не уменьшится сам по себе. Для восстановления этого размера вы должны вызвать функцию LocalShrink.

Освобождение локального блока памяти

Для освобождения локального блока памяти, полученного от функции LocalAlloc, вы должны использовать функцию LocalFree :

Идентификатор освобождаемого блока передается функции в качестве ее единственного параметра.

Функция возвращает NULL при успешном завершении или значение hloc при ошибке.

Перед освобождением зафиксированных блоков памяти их следует предварительно расфиксировать.

Инициализация локальной области данных в заданном сегменте

Для создания и инициализации локальной области данных в заданном сегменте вы можете воспользоваться функцией LocalInit :


Параметр uSegment перед вызовом функции должен содержать идентификатор сегмента, который будет содержать локальную область данных.

Параметр uStartAddr определяет начальный адрес локальной области данных, а параметр uEndAddr — конечный адрес локальной области данных.

Первые 16 байт в сегменте данных необходимо зарезервировать для системы.

Приложение LMEM

Приведем исходный текст приложения LMEM, которое работает аналогично приложению GMEM, но с использованием локальной области памяти (листинг 2.5).

Листинг 2.5. Файл lmem/lmem.cpp

Файл определения модуля приложения LMEM приведен в листинге 2.6.

Листинг 2.6. Файл lmem/lmem.def

В этом файле начальное значение локальной области данных установлено равным 4096 байт. Проверяя работу приложения LMEM, вы можете попробовать уменьшить размер локальной области данных, например, до величины 1 Кбайт, а затем заказать локальный блок памяти размером 10 Кбайт. В этом случае несмотря на то, что сразу после запуска приложения в локальной области данных будет свободно всего несколько сотен байт, запрос на 10 Кбайт будет удовлетворен за счет автоматического увеличения размера локальной области данных.

Статическая память

Статические данные, описанные в приложении Windows с использованием ключевого слова static или объявленные как внешние переменные располагаются в автоматическом сегменте данных приложения (рис. 2.10).

В документации к SDK не рекомендуется в моделях памяти small и medium использовать дальние указатели на статические данные (См. раздел 16.5 руководства, который называется Traps to Avoid When Managing Program Data).

Дело в том, что автоматический сегмент данных приложения является перемещаемым. Операционная система Windows фиксирует сегмент данных при активизации приложения и расфиксирует его во время переключения на другие приложения. Поэтому логический адрес сегмента данных может изменяться.

Следующий способ является недопустимым:

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

Рекомендуется в указанной выше ситуации использовать ближний статический указатель с явным преобразованием типа к LPSTR:

В процессе явного преобразования типа используется текущее содержимое регистра DS, а не то, которое использовалось при загрузке приложения в память.

Автоматическая память

Автоматические данные располагаются, как и статические, в автоматическом сегменте данных (рис. 2.10), назначаемым приложению при его загрузке в память. К автоматическим данным относится стек, параметры функций и локальные переменные.

Как мы уже говорили, размер стека определяется оператором STACKSIZE в файле определения модуля и не увеличивается автоматически во время работы приложения.

Дополнительная память в структуре класса окна

При регистрации класса окна вы можете в поле cbClsExtra структуры WNDCLASS указать размер дополнительной области памяти, которая будет зарезервирована в структуре данных, описывающей класс окна. В эту область можно записать данные, предназначенные для использования всеми окнами, создаваемыми на базе класса.

Для работы с этой дополнительной памятью предназначены функции SetClassWord, SetClassLong, GetClassWord, GetClassLong.

Функция SetClassWord устанавливает в структуре, описывающей класс для окна hwnd, новое значение wNewWord, при этом смещение устанавливаемого слова определяется параметром offset:

Для параметра offset вы должны использовать значения от нуля до указанного в поле cbClsExtra минус 2 или следующие значения:

Значение Описание
GCW_HBRBACKGROUND Идентификатор кисти для закрашивания фона окна
GCW_HCURSOR Идентификатор курсора
GCW_HICON Идентификатор пиктограммы
GCW_STYLE Стили окна

С помощью перечисленных выше четырех значений вы можете изменить характеристики класса окна. Эти изменения будут учитываться только для вновь создаваемых окон.

В случае ошибки функция SetClassWord возвращает нулевое значение.

Функция GetClassWord позволяет вам прочитать содержимое слова дополнительной области памяти со смещением offset:

Для этой функции вы можете использовать те же значения, что и для предыдущей, плюс еще два:

Значение Описание
GCW_CBCSLEXTRA Размер дополнительной области памяти в структуре класса окна
GCW_CBWNDEXTRA Размер дополнительной области памяти в структуре окна
GCW_HBRBACKGROUND Идентификатор кисти для закрашивания фона окна
GCW_HCURSOR Идентификатор курсора
GCW_HICON Идентификатор пиктограммы
GCW_STYLE Стили окна

Функция GetClassWord возвращает значение указанного слова из структуры класса окна или нулевое значение при ошибке.

Функция SetClassLong аналогична функции SetClassWord, но работает с двойными словами:

Для параметра offset дополнительно можно указать значение GCL_WNDPROC, при этом функция заменит адрес функции окна. Мы пользовались этим приемом в приложении SMARTPAD, перехватывая управление у стандартной функции окна органа управления класса «edit».

В случае ошибки функция SetClassLong возвращает нулевое значение.

С помощью функции GetClassLong вы можете получить из структуры класса окна значение двойного слова, расположенного со смещением offset:

Для этой функции можно указать положительное смещение или одну из двух констант — GCL_WNDPROC и GCL_MENUNAME. В первом случае функция GetClassLong возвратит адрес функции окна для данного класса, во втором — указатель на строку имени меню, указанного при регистрации класса.

Дополнительная память в структуре окна

При регистрации класса окна функцией RegisterClass вы можете в поле cbWndExtra структуры WNDCLASS указать размер дополнительной области памяти, которая будет зарезервирована в структуре, описывающей каждое окно, создаваемое на базе данного класса.

Для работы с этой дополнительной памятью предназначены функции SetWindowWord, SetWindowLong, GetWindowWord, GetWindowLong.

Функция SetWindowWord устанавливает в структуре, описывающей окно hwnd, новое значение wNewWord, при этом смещение устанавливаемого слова определяется параметром offset:

Для параметра offset вы должны использовать значения от нуля до указанного в поле cbClsExtra минус 2 или следующие значения:

Значение Описание
GWW_HINSTANCE Идентификатор приложения, владеющего данным окном
GWW_ID Идентификатор дочернего окна

В случае ошибки функция SetWindowWord возвращает нулевое значение.

Функция GetWindowWord позволяет вам прочитать содержимое слова дополнительной области памяти в структуре окна со смещением offset:

Для этой функции вы можете использовать следующие значения:

Значение Описание
GWW_HINSTANCE Идентификатор приложения, владеющего данным окном
GWW_HWNDPARENT Идентификатор родительского окна
GWW_ID Идентификатор дочернего окна

Функция GetWindowWord возвращает значение указанного слова из структуры класса окна или нулевое значение при ошибке.

Функция SetWindowLong аналогична функции SetWindowWord, но работает с двойными словами:

Для параметра offset дополнительно можно указать следующие значения:

Значение Описание
GWL_EXSTYLE Расширенный стиль окна
GWL_STYLE Стиль окна
GWL_WNDPROC Указатель на функцию окна

Если параметр hwnd содержит идентификатор диалоговой панели, вы можете использовать еще несколько значений:

Значение Описание
DWL_MSGRESULT Значение, возвращенное при обработке сообщения в функции диалоговой панели
DWL_USER Дополнительная информация, имеющая отношение к приложению, такая как идентификаторы или указатели
DWL_DLGPROC Указатель на функцию диалоговой панели

В случае ошибки функция SetWindowLong возвращает нулевое значение.

С помощью функции GetWindowLong вы можете получить из структуры окна значение двойного слова, расположенного со смещением offset:

Для этой функции можно указать положительное смещение или одну из констант, описанных выше для функции SetWindowLong .

Ресурсы приложения

Управление ресурсами было рассмотрено нами в предыдущем томе «Библиотеки системного программиста». Как вы знаете, ресурсы представляют собой данные, расположенные в файле загрузочного модуля приложения и доступные только для чтения.

В файле описания ресурсов вы можете указать, что для хранения ресурсов следует использовать фиксированную, перемещаемую или удаляемую память. Вы можете описать ресурсы, как загружаемые в память при запуске приложения (PRELOAD) или по требованию (LOADONCALL).

Загрузка ресурсов в оперативную память выполняется такими функциями, как LoadIcon или CreateDialog . Для загрузки ресурсов, имеющих нестандартный формат, вы должны использовать функции FindResource (поиск ресурса и получение идентификатора ресурса) и LoadResource (загрузка ресурса и получение идентификатора блока памяти, в который загружен найденный ресурс).

Все эти функции были описаны в предыдущем томе, однако для удобства мы приведем их краткое описание еще раз.

Приведем прототип функции FindResource :

Параметр hInst является идентификатором модуля, содержащего ресурс. Для извлечения ресурса из приложения вы должны указать его идентификатор, передаваемый функции WinMain через параметр hInstance.

Параметр lpszName должен содержать адрес имени ресурса. Для загрузки произвольных данных в качестве этого параметра следует передать указатель на строку, содержащую идентификатор ресурса.

Функции FindResource в качестве третьего параметра можно передавать идентификаторы предопределенных типов ресурсов, список которых приведен ниже.

Идентификатор ресурса Название ресурса
RT_ACCELERATOR Таблица акселераторов
RT_BITMAP Изображение bitmap
RT_CURSOR Курсор
RT_DIALOG Диалоговая панель
RT_FONT Шрифт
RT_FONTDIR Каталог шрифтов
RT_ICON Пиктограмма
RT_MENU Меню
RT_RCDATA Произвольные данные
RT_STRING Таблица строк

Вы можете использовать функцию FindResource для загрузки таких ресурсов, как пиктограммы или курсоры, указав ей тип ресурса, соответственно, RT_ICON или RT_CURSOR. Однако в документации к SDK сказано, что загрузку предопределенных ресурсов, таких как пиктограммы и курсоры, следует выполнять специально предназначенными для этого функциями (LoadIcon, LoadCursor и т. д.).

После того как ресурс найден, его следует загрузить, вызвав функцию LoadResource :

Параметр hinst представляет собой идентификатор модуля, из файла которого загружается ресурс. Если ресурс загружается из файла вашего приложения, используйте значение hInstance, полученное через соответствующий параметр функции WinMain.

В качестве второго параметра этой функции следует передать значение, полученное от функции FindResource.

Для получения логического адреса загруженного ресурса его необходимо зафиксировать в памяти, вызвав функцию LockResource :

В качестве параметра hGlb функции LockResource следует передать идентификатор ресурса, полученный от функции LoadResource.

Функция LockResource фиксирует данные в памяти и возвращает дальний указатель на соответствующий буфер. После фиксирования Windows не станет удалять сегмент с ресурсами из памяти, так что приложение сможет использовать данные в любой момент времени.

После того как приложение использовало ресурс и он стал ненужен, следует расфиксировать память ресурса, вызвав функцию UnlockResource . Функция определена через функцию GlobalUnlock следующим образом:

Перед завершением работы приложения следует освободить полученный ресурс, вызвав функцию FreeResource :

В качестве параметра hGlb следует передать идентификатор ресурса, полученный от функции LoadResource.

LocalAlloc Vs GlobalAlloc Vs malloc Vs new

I have searched for this on various links, but still the doubt persist.

I do not understand the difference between LocalAlloc vs GlobalAlloc vs malloc vs new for memory allocation.

I have gone through this link of MSDN:

Please explain the following statement:

The malloc function has the disadvantage of being run-time dependent. The new operator has the disadvantage of being compiler dependent and language dependent

2 Answers 2

Back in the days of 16-bit Windows, the difference was significant.

In 16-bit Windows, memory was accessed through values called “selectors”, each of which could address up to 64K. There was a default selector called the “data selector”; operations on so-called “near pointers” were performed relative to the data selector. For example, if you had a near pointer p whose value was 0x1234 and your data selector was 0x012F, then when you wrote *p, you were accessing the memory at 012F:1234. (When you declared a pointer, it was near by default. You had to say FAR explicitly if you wanted a far pointer.)

Илон Маск рекомендует:  Что такое код tranmitcommchar

Important: Near pointers are always relative to a selector, usually the data selector.

The GlobalAlloc function allocated a selector that could be used to access the amount of memory you requested. You could access the memory in that selector with a “far pointer”. A “far pointer” is a selector combined with a near pointer. (Remember that a near pointer is relative to a selector; when you combine the near pointer with an appropriate selector, you get a far pointer.)

Every instance of a program and DLL got its own data selector, known as the HINSTANCE. Therefore, if you had a near pointer p and accessed it via *p from a program executable, it accessed memory relative to the program instance’s HINSTANCE. If you accessed it from a DLL, you got memory relative to your DLL’s HINSTANCE.

Therefore, that in 16-bit Windows, the LocalAlloc and GlobalAlloc functions were completely different! LocalAlloc returned a near pointer, whereas GlobalAlloc returned a selector.

Pointers that you intended to pass between modules had to be in the form of “far pointers” because each module has a different default selector. If you wanted to transfer ownership of memory to another module, you had to use GlobalAlloc since that permitted the recipient to call GlobalFree to free it.

Even in Win32, you have to be careful not to confuse the local heap from the global heap. Memory allocated from one cannot be freed on the other. All the weirdness about near and far pointers disappeared with the transition to Win32. But the local heap functions and the global heap functions are nevertheless two distinct heap interfaces.

Also, the link specified by you clearly says that,

Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that call HeapAlloc using a handle to the process’s default heap, and HeapAlloc can be instructed to raise an exception if memory could not be allocated, a capability not available with LocalAlloc.

For your confusion on malloc vs new, Billy ONeal’s answer summarizes that pretty clearly.

For the difference between malloc and HeapAlloc, David Heffernan’s and Luis Miguel Huapaya’s answer combined gives the perfect solution::

В Windows, как я могу заменить « GlobalAlloc` с new`?

В Windows, как я могу заменить GlobalAlloc с участием new ?

Привет, У меня есть этот фрагмент кода (здесь: ««Чтение из Mailslot») что выделение памяти с GlobalAlloc .

Я хотел бы изменить код и использовать смарт-указатель, а не голый LPTSTR (И избавиться от GlobalFree ) а также new вместо GlobalAlloc . cbMessage является «Размер следующего сообщения в байтах» и поэтому мне нужно что-то вроде malloc который работает для нетипизированной памяти, есть ли форма new подходит к моему случаю?

2 ответа

Возможно, для Вашего проекта будут необходимы бесплатные векторные карты. На нашем сайте представлены карты для всех стран.

Как правило, вы не можете.

Различные функции распределения памяти ( GlobalAlloc , malloc , new , SysAlloc , VirtualAlloc , HeapAlloc ) Существует потому, что они распределяют память по-разному, разные места, разных размеров, маркировать его по-разному, используют различные базовые менеджер, и множество других различий. Некоторые из них находятся в локальной куче, некоторые глобальные, некоторые виртуальные, некоторые не уточняют, другие, которые резервируют память и делать вещи с ним, такие как SysAllocString, другие, которые работают с COM, как CoGetMalloc, и так далее.

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

Для того, чтобы использовать смарт-указатели с другими распределителями, есть несколько вещей, которые вы можете сделать. Простейшие обеспечивают их распределитель и deallocator функций на смарт-класс указателя, что позволяет ему обрабатывать вещи должным образом. В зависимости от указателя выбора, может потребоваться некоторые настройки, или вы, возможно, придется собрать основные смарт-указатель, способный работать с этим распределителем.

Для распространенных, MFC и/или АТЛ часто есть умные указатели и вспомогательные функции, которые работают с одним или более специализированными распределителями. При использовании тех возможно, вы можете смотреть на это.

ВИДЕОКУРС
выпущен 4 ноября!

Описание:
function GlobalAlloc(Flags: Word; Bytes: Longint): THandle;

Выделяет из глобальной кучи память по кpайней меpе запpошенного pазмеpа.

Паpаметpы:
Flags: Маска флагов. Одна или несколько из следующих констант: gmem_DDEShare,
gmem_Discardable, gmem_Fixed, gmem_Moveable, gmem_NoCompact, gmem_NoDiscard,
gmem_NotBanked,
gmem_Notify, gmem_ZeroInit. См. pаздел «Флаги глобальной памяти, gmem_» в главе
1.

Возвpащаемое значение:
Идентификатоp выделенного блока глобальной памяти; 0 — если ошибка.

GlobalAlloc и адресация структуры

У меня небольшой вопрос по-поводу программирования на TASM (думаю он
также касатеся и других ассемблеров).

Пишу на TASMe под Win не первый день. Но вот наткнулся на такую
ситуацию:

пишу прогу, которая по ходу выполения должна порождать потоки. (Типа
Web или FTP сервера). Когда пользователь подключается, для него
создается новый поток и выделяется память через GlobalAlloc.
Есть довольно непростая структура данных, для которой у Винды и просим
память. Адресую структуру естественно так: в eax помещаю адрес
выделенного участка и пишу, например mov edx,[eax+смещение] или lea
edx,[eax+смещение].

Можно вручную прописать макрозначения типа такого

и т.д.
но если структкра приличная, то труд получается нелегкий.

Можно все это объявить в udataseg

и обращатся так

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

Собственно вопрос: есть ли такие средства в TASM,
чтобы объявить эту структуру, но не в памяти основной проги, а просто
так, чтобы вместо вычисляемого смещения, можно было писать имена
переменных?

GlobalAlloc объяснение

Это строка кода в вопросе, который я использую из учебника. Я читаю из EDITTEXT . Я в основном хотел бы знать , где GPTR пришел, и что это за. Она не была определена где — либо еще в коде.

У меня есть базовое понимание остальной части линии, но MSDN объяснения «s не совсем понятно. Они говорят , что это:

Может кто — то объяснить на простом английском языке , где GPTR от, для чего это, и как это относится к __in UINT uFlags ? Я знаю , что это , unsigned int но тогда знавшие останавливается.

GPTR является следующим å комбинации GMEM_FIXED и GMEM_ZEROINIT (OR).

uFlags
Атрибуты распределения памяти. Если задано нулевое значение по умолчанию является GMEM_FIXED. Этот параметр может быть один или несколько из следующих значений, для несовместимых комбинаций, которые специально отмеченных исключения.

Значение Значение
GHND 0x0042 Объединяет GMEM_MOVEABLE и GMEM_ZEROINIT.
GMEM_FIXED 0x0000 Распределяет фиксированной памяти. Возвращаемое значение является указателем.
GMEM_MOVEABLE 0x0002 Распределяет подвижную память. Блоки памяти никогда не перемещались в физической памяти, но они могут быть перемещены в кучи по умолчанию. Это значение не может быть объединено с GMEM_FIXED.
GMEM_ZEROINIT 0x0040 инициализация содержимого памяти к нулю.
GPTR 0x0040 Объединяет GMEM FIXED и GMEM_ZEROINIT.

Что такое код globalalloc

Allocates the specified number of bytes from the heap.

Syntax

Parameters

The memory allocation attributes. If zero is specified, the default is GMEM_FIXED. This parameter can be one or more of the following values, except for the incompatible combinations that are specifically noted.

Combines GMEM_MOVEABLE and GMEM_ZEROINIT.

Allocates fixed memory. The return value is a pointer.

Allocates movable memory. Memory blocks are never moved in physical memory, but they can be moved within the default heap.

The return value is a handle to the memory object. To translate the handle into a pointer, use the GlobalLock function.

This value cannot be combined with GMEM_FIXED.

Initializes memory contents to zero.

Combines GMEM_FIXED and GMEM_ZEROINIT.

The following values are obsolete, but are provided for compatibility with 16-bit Windows. They are ignored.

GMEM_DDESHARE GMEM_DISCARDABLE GMEM_LOWER GMEM_NOCOMPACT GMEM_NODISCARD GMEM_NOT_BANKED GMEM_NOTIFY GMEM_SHARE dwBytes [in]

The number of bytes to allocate. If this parameter is zero and the uFlags parameter specifies GMEM_MOVEABLE, the function returns a handle to a memory object that is marked as discarded.

Return value

If the function succeeds, the return value is a handle to the newly allocated memory object.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Remarks

Windows memory management does not provide a separate local heap and global heap. Therefore, the GlobalAlloc and LocalAlloc functions are essentially the same.

The movable-memory flags GHND and GMEM_MOVABLE add unnecessary overhead and require locking to be used safely. They should be avoided unless documentation specifically states that they should be used.

New applications should use the heap functions to allocate and manage memory unless the documentation specifically states that a global function should be used. For example, the global functions are still used with Dynamic Data Exchange (DDE), the clipboard functions, and OLE data objects.

If the GlobalAlloc function succeeds, it allocates at least the amount of memory requested. If the actual amount allocated is greater than the amount requested, the process can use the entire amount. To determine the actual number of bytes allocated, use the GlobalSize function.

If the heap does not contain sufficient free space to satisfy the request, GlobalAlloc returns NULL. Because NULL is used to indicate an error, virtual address zero is never allocated. It is, therefore, easy to detect the use of a NULL pointer.

Memory allocated with this function is guaranteed to be aligned on an 8-byte boundary. To execute dynamically generated code, use the VirtualAlloc function to allocate memory and the VirtualProtect function to grant PAGE_EXECUTE access.

To free the memory, use the GlobalFree function. It is not safe to free memory allocated with GlobalAlloc using LocalFree.

Examples

The following code shows a simple use of GlobalAlloc and GlobalFree.

Requirements

Minimum supported client

Windows XP [desktop apps | UWP apps]

Minimum supported server

Windows Server 2003 [desktop apps | UWP apps]

Описание GlobalAlloc

Это строка кода, о которой я расскажу в учебнике. Я читаю с EDITTEXT . В основном я хотел бы узнать, откуда вышло GPTR , и для чего он нужен. Он не был определен нигде в коде.

У меня есть базовое понимание остальной части линии, но объяснение MSDN не совсем понятно. Они говорят, что это:

Может кто-то объяснить на простом английском языке, где GPTR от, для чего это, и как это относится к __in UINT uFlags ? Я знаю, что это unsigned int , но тогда знание останавливается.

Создан 10 ноя. 10 2010-11-10 02:51:01 Ben

2 ответа

GPTR 0x0040 Объединяет GMEM_FIXED и GMEM_ZEROINIT.

Как вы можете видеть, это просто немного шаблона (0x0040) и может быть объединено с другими допустимыми флагами

Создан 10 ноя. 10 2010-11-10 03:02:18 Chubsdad

Ах, спасибо, это прекрасно. Не достаточно углубленно. – Ben 10 ноя. 10 2010-11-10 03:03:30

GPTR является следующим å сочетания GMEM_FIXED и GMEM_ZEROINIT (OR).

uFlags
Атрибуты распределения памяти. Если указан ноль, по умолчанию используется GMEM_FIXED. Этот параметр может быть одним или несколькими из следующих значений, за исключением несовместимых комбинаций, которые специально указаны.

Значение Значение
GHND 0x0042 Объединяет GMEM_MOVEABLE и GMEM_ZEROINIT.
GMEM_FIXED 0x0000 Выделение фиксированной памяти. Возвращаемое значение является указателем.
GMEM_MOVEABLE 0x0002 Выделяет подвижную память. Блоки памяти никогда не перемещаются в физической памяти, но их можно перемещать в кучу по умолчанию. Это значение нельзя комбинировать с GMEM_FIXED.
GMEM_ZEROINIT 0x0040 Инициализирует содержимое памяти до нуля.
GPTR 0x0040 Комбинирует GMEM FIXED и GMEM_ZEROINIT.

Создан 10 ноя. 10 2010-11-10 03:02:48 wengseng

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL
Value Meaning
GHND 0x0042
GMEM_FIXED 0x0000
GMEM_MOVEABLE 0x0002
GMEM_ZEROINIT 0x0040
GPTR 0x0040