Руководство по языку B.Pascal 7

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


Для модуля Graph предусмотрены две программы управления ди- намически распределяемой областью GraphFrееМем и GraphGetМем. Первая из них освобождает память, распределенную для драйверов, а вторая - распределяет память для драйверов графических устройств. Стандартные программы имеют следующий вид:

procedure GraphGetMem(var P : Pointer; Size : word); { выделить память для драйверов графических устройств }

procedure GraphFreeMem(var P : Pointer; Size : word); { освободить память для драйверов графических устройств }

В модуле Graph имеются два указателя, которые по умолчанию указывают на две описанные здесь стандартные подпрограммы. Эти указатель определяются следующим образом:

var GraphGetMemPtr : pointer; { указатель на программу распределения памяти } GraphFreeMemPtr : pointer; { указатель на программу освобождения памяти }

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

* для многоцелевых графических буферов, размер которых уста- навливается вызовов SegGraphBufSize (по умолчанию это 4К);

* для драйвера устройства, загружаемого InitGraph (файлы *.BGI);

* для файла векторного шрифта, загруженного SetTextStyle (файлы *.CHR).

Графический буфер всегда выделяется в динамически распреде- ляемой области памяти. Память для драйвера устройства выделяется в динамической памяти, если программа не загружает его или не компонуется с ним вызовом RegisterBGIdriver. При выборе векторно- го шрифта с помощью SetTextStyle также выделяется память в дина- мически распределяемой области (если ваша программа не компонует- ся со шрифтом и не использует RegisterBGIfont).

Чтобы задать ваше собственное управление памятью, в модуле Graph вы можете изменить значения этих указателей так, чтобы они ссылались на ваши собственные программы. Программы, заданные пользователем, должны иметь тот же список параметров, что и стан- дартные программы, и должны иметь дальний тип вызова. Приведем далее пример заданных пользователем программ распределения и ос- вобождения памяти. Заметим, что при использовании процедуры Eхit автоматически вызывается процедура CloseGraph.


program UserHeapManegement; { программа показывает, как пользователь может работать с подпрограммами управления динамически распределяемой об- ластью памяти, используемыми в модуле Graph } uses Graph; var GraphDriver, GraphMode : Integer; ErrorCode : Integer; { используется для сохранения кода возврата функции GraphResult } PreGraphExitProc : Pointer { используется для сох- ранения исходной процедуры выхода } { процедуры пользователя должны использовать дальний тип обращения } procedure MyGetMem(var P : Pointer; Size : word); far; { выделить память для драйверов графических устройств } begin Write('Была вызвана процедура ', 'MyGetMem, нажмите <Enter>:'); GetMem(P, Size); end; { MyGetMem }

procedure MyFreeMem(ver P : Pointer; Size : word); far; { освободить память, занятую драйверами графических устройств } begin RestoreCRTMode; Write('Была вызвана процедура MyFreeMem, нажмите ', '<Enter>:'); Readln; if P <> Nil Then { не освобождать пустые указатели } begin FreeMem(P, Size); P := Nil; end; { MyFreeMem }

procedure MyExitProc; far; { процедура всегда получает вызов при прекращении работы программы } begin ExitProc := PreGraphExitProc; { восстановить исходную процедуру выхода } CloseGraph; { очистить динамически распределяемую область } end; { MyExitProc }

begin { инициализировать программу очистки памяти } PreGraphExitProc := ExitProc; ExitProc := @MyExitProc;

GraphGetMemPtr := @MyGetMem ; { заменить распределение памяти } GraphFreeMemPtr := @MyFreeMem ; { заменить освобождение памяти } GraphDriver := Detect; InitGraph(GraphDriver, GraphMode, ''); ErrorCode := GraphResult; if ErrorCode <> grOk then begin Writeln('Графическая ошибка: ' GraphErrorMsg(ErrorCode); Readln; Halt(1); end; Line(0, 0, GetMaxX, GetMaxY); OutText(1, 1, 'Нажмите клавишу <Enter>:'); Readln; end. { UserHeapManegement }

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

procedure MyGetMem(var P: Pointer; Size: Word); far; var P: Pointer; bagin P:= GlobalAllocPtr(HeapAllocFlags, Size); GetMem(P, 4096); end; { MyGetMem }


Содержание раздела