11.5.2. Процедуры Dispose и FreeMem
Процедура Dispose (VAR P : Pointer ) освобождает память, занимаемую динамической переменной P^, на которую указывает ее
- 202 -
аргумент P. Эта процедура работает только с типизированными ссылочными переменными. Во избежание проблем вызовы Dispose должны быть парны вызовам New с тем же аргументом и ни в коем случае не применяться к неразмещенным ссылкам.
После выполнения процедуры Dispose значение ссылки P не определено, как и значение разыменования P^.
Для освобождения непрерывных участков памяти заданного размера нужно использовать процедуру
FreeMem( VAR Р : Pointer; Size : Word ).
Она производит освобождение участка памяти, начиная с адреса, передаваемого ей в первом параметре (ссылке или указателе P) и имеющего размер, определяемый вторым параметром (Size). При использовании процедуры FreeMem нельзя забывать, что размер освобождаемого блока должен точно соответствовать размеру, заданному при его размещении посредством GetMem или New. В противном случае либо возникнут потерянные байты, если размер блока при освобождении оказался меньше (а это мусор в памяти), либо в дальнейшем возможна потеря части данных, непосредственно примыкавших к этой области, если размер освобождаемого блока больше ранее отведенного. Последнее чревато особо неприятными последствиями.
Вызовы FreeMem, как и Dispose, в идеале должны быть парны вызовам GetMem. Хотя на практике можно использовать FreeMem вместо Dispose.
Значение ссылочной переменной P после вызова FreeMem считается неопределенным, и ссылаться на P^ в этом случае не стоит.
Если сразу за операторами Dispose или FreeMem следуют конец всей программы или оператор Halt и ему подобные, то можно, в принципе, исключить из программы эти последние процедуры освобождения. Это не совсем по правилам, но может доставить немного радости тем, кто вечно воюет с размером собственных программ. Все сказанное в этом абзаце не относится к резидентным программам.
11.5.3. Процедуры Mark и Release
Механизм действия этих процедур следующий. Пусть переменная P имеет предопределенный тип Pointer, а P1, P2, P3 и P4 объявлены как ссылочные переменные. Пусть текст программы содержит фрагмент
- 203 -
...
New(P1);
New(P2);
Mark(P); { вызов Mark }
New(P3);
New(P4);
...
Release(P); { вызов Release }
...
Перед вызовом процедуры Release куча будет иметь вид, как на рис. 11.4.
Рис. 11. 4
При вызове процедуры Mark в переменную P записалось значение HeapPtr, которое было сразу после размещения P2. Далее были размещены P3 и P4, и указатель HeapPtr передвинулся туда, где он изображен на рис. 11.4.