TURBO PASCAL |
Новости
|
Управление памятьюПри разработке программ, работающих с динамической памятью, обычно используются стандартные процедуры New, Dispose, GetMem и FreeMem. Однако получить доступ к администратору памяти защищен- ного режима Borland вы можете с помощью функций GlobalXXXX в мо- дуле WinAPI. Заметим, что функции GlobalXXXXPtr комбинируют в одной подп- рограмме общие последовательности вызовов функций, такие как GlobalAlloc, за которыми следуют вызовы GlobalLock, GlobalUnlock или GlobalFree. Подпрограммы управления памятью API Таблица 17.2 ┌─────────────────────┬─────────────────────────────────────────┐ │ Функция │ Описание │ ├─────────────────────┼─────────────────────────────────────────┤ │ GetFreeSpace │ Определяет объем свободной памяти в ди-│ │ │ намически распределяемой области. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalAlloc │ Выделяет блок памяти в динамически расп-│ │ │ ределяемой области. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalAllocPtr │ Выделяет и блокирует блок памяти (с по-│ │ │ мощью вызовов GlobalAlloc и GlobalLock).│ │ │ │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalCompact │ Переупорядочивает память, распределен-│ │ │ ную в динамической области, так что ос-│ │ │ вобождается заданный объем памяти. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalDiscard │ Выгружает заданный объект памяти. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalDosAlloc │ Распределяет память, к которой можно по-│ │ │ лучить доступ в реальном режиме DOS. Эта│ │ │ память будет существовать в первом мега-│ │ │ байте линейного адресного пространства. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalDosFree │ Освобождает память, выделенную ранее с│ │ │ помощью GlobalDosAlloc. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalFlags │ Получает информацию о блоке памяти. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalFree │ Освобождает разблокированный блок памяти│ │ │ и делает его описатель недействительным.│ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalFreePtr │ Разблокирует и освобождает блок памяти│ │ │ с помощью GlobalUnlock и GlobalFree. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalHandle │ Получает описатель объекта в памяти по│ │ │ заданному адресу сегмента. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalLock │ Увеличивает счетчик ссылки блока памяти│ │ │ и возвращает указатель на него. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalLockPtr │ То же, что и GlobalLock, но вместо опи-│ │ │ сателя воспринимает указатель. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalLRUNewest │ Перемещает объект в памяти на новую не-│ │ │ давно используемую позицию, минимизируя,│ │ │ таким образом, вероятность выгрузки│ │ │ объекта. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalLRUOldest │ Перемещает объект в памяти на самую│ │ │ "старую" недавно используемую позицию,│ │ │ максимизирую вероятность выгрузки объ-│ │ │ екта. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalNorify │ Вызывает адрес экземпляра процедуры уве-│ │ │ домления, передавая описатель блока, ко-│ │ │ торый нужно выгрузить. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalPageLock │ Увеличивает значение счетчика блокиров-│ │ │ ки для памяти, связанной с данным селек-│ │ │ тором. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalPageUnlock │ Уменьшает значение счетчика блокировки│ │ │ для памяти, связанной с данным селекто-│ │ │ ром. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalPtrHandle │ По заданному указателю на блок памяти│ │ │ возвращает описатель этого блока. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalReAlloc │ Перераспределяет блок памяти. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalReAllocPtr │ Разблокирует, перераспределяет и блоки-│ │ │ рует блок памяти (используя функции│ │ │ GlobalUnlock, GlobalReAlloc и│ │ │ GlobalLock). │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalSize │ Определяет текущий размер блока памяти. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalUnfix │ Разблокирует блок памяти, блокированный│ │ │ ранее с помощью GlobalLock. │ ├─────────────────────┼─────────────────────────────────────────┤ │ GlobalUnockPtr │ То же, что и GlobalUnlock, но вместо│ │ │ описателя воспринимает указатель. │ ├─────────────────────┼─────────────────────────────────────────┤ │ LockSegment │ Блокирует заданный выгружаемый сегмент. │ ├─────────────────────┼─────────────────────────────────────────┤ │ UnlockSegment │ Разблокирует сегмент. │ └─────────────────────┴─────────────────────────────────────────┘ Функция GlobalAlloc используется для распределения блоков памяти. Для их освобождения применяется функция GlobalFree. Адми- нистратор памяти поддерживает три типа блоков памяти: фиксирован- ный, перемещаемый и выгружаемый. Фиксированный блок остается в одних и тех же адресах физической памяти. Перемещаемый блок может перемещаться в физической памяти и освобождать место для других запросов на выделение памяти, а выгружаемые блоки могут выгру- жаться из памяти, освобождая место для других блоков. С помощью передаваемых GlobalAlloc флагов вы можете выбрать один из этих трех типов: * gmem_Fixed (фиксированный) * gmem_Moveable (перемещаемый) * gmem_Moveable + gmem_Discardable (выгружаемый) Прикладная программа обычно выделяет только перемещаемые блоки памяти, которые представляются типом THandle в модуле WinAPI. Описатель памяти - это значение размером в слово, которое идентифицирует блок памяти аналогично тому, как описатель файла - это значение размером в слово, идентифицирующее открытый файл. Перед тем как вы сможете получить доступ к памяти, его нужно заблокировать с помощью функции GlobalAlloc, а когда вы закончите к нему обращаться, его нужно разблокировать с помощью функции GlobalUnlock. GlobalLock возвращает полный 32-разрядный указатель на первый байт блока. Смещение указателя всегда равно 0. В защи- щенном режиме DOS селектор указателя - это тоже самое, что описа- тель блока, но в Windows это не всегда так. Правильная последовательность вызовов для выделения, блоки- ровки, разблокировки или освобождения блока показана в приведен- ном ниже примере. В данном примере H - это переменная типа THandle, а P - указатель: H := GlobalAlloc(gmem_Moveable, 8192); { выделение блока } if H <> then { если память выделена } begin P := GlobalLock(H); { блокировка блока } . . { доступ к блоку через P } . GlobalUnlock(H); { разблокировать блок } GlobalFree(H); { освободить блок } end; Блокировка и разблокировка блока при каждом обращении к нему достаточно утомительна и ведет к ошибкам, и реально она необходи- ма только для выгружаемых блоков и в прикладных программах Windows, работающих в реальном режиме. Во всех других ситуациях лучшим решением является блокировка блока сразу после его выделе- ния и сохранение этого состояния до освобождения блока. С этой целью модуль WinAPI включает в себя семейство подпрограмм-"оболо- чек" GlobalXXXXPtr. Особый интерес представляет функция GlobalAllocPtr, которая выделяет и блокирует блок памяти, и функ- ция GlobalFreePtr, разблокирующая и освобождающая блок памяти. С помощью этих подпрограмм приведенный выше пример можно упростить: H := GlobalAlloc(gmem_Moveable, 8192); { выделение блока } if H <> then { если память выделена } begin . . { доступ к блоку } . GlobalFreePtr(P); { освободить блок } end; Вызвав функцию GlobalReAlloc, вы можете изменить размер или атрибуты блока памяти, сохранив его содержимое. Функция GlobalReAlloc возвращает новый описатель блока, который может от- личаться от передаваемого функции описателя, если старый размер или новый размер блок превышает 64К. Заметим, что в тех случаях, когда старый размер блока и новый его размер меньше 64К, GlobalReAlloc всегда может изменить размер блока, не изменяя его описателя. Функция GlobalReAlloc можно также использоваться для измене- ния атрибутов блока. Это можно сделать, задав наряду с gmem_Moveable или gmem_Discardable флаг gmem_Modify. Функция GlobalReAlloc выполняет те же действия, что и GlobalReAlloc, но обе они вместо описателей использует указатели. Имеется также ряд других, менее часто используемых GlobalXXXX. Все они подробно описаны в Главе 1 ("Справочник по библиотеке") "Справочного руководства программиста". |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |