Адреса и размеры свободных блоков, созданных при операциях Dispose и FrееМем, хранятся в списке свободных блоков, который увеличивается вниз, начиная со старших адресов памяти, в сегменте динамически распределяемой области. Каждый раз перед выделением памяти для динамической переменной, перед тем, как динамически распределяемая область будет расширена, проверяется список сво- бодных блоков. Если имеется блок соответствующего размера (то есть размер которого больше или равен требуемому размеру), то он используется.
Процедура Rеlеаsе всегда очищает список свободных блоков. Таким образом, программа динамического распределения памяти "за- бывает" о незанятых блоках, которые могут существовать ниже ука- зателя динамически распределяемой области. Если вы чередуете об- ращения к процедурам Маrk и Rеlеаsе с обращениями к процедурам Dispose и FrееМем, то нужно обеспечить отсутствие таких свободных блоков.
Переменная FreeList модуля System указывает на первый сво- бодный блок динамически распределяемой области памяти. Данный блок содержит указатель на следующий свободный блок и т.д. Пос- ледний свободный блок содержит указатель на вершину динамически распределяемой области (то есть адрес, заданный HeapPtr). Если свободных блоков в списке свободных блоков нет, то FreeList будет равно HeapPtr.
Формат первых 8 байт свободного блока задается типом TFreeRec: type PFreeRec = ^TFreeRec; TFreeRec = record Next: PFreeRec; Size: Pointer; end;
Поле Next указывает на следующий свободный блок, или на ту же ячейку, что и HeapPtr, если блок является последним свободным блоком. В поле Size записан размер свободного блока. Значение в поле Size представляет собой не обычное 32-битовое значение, а "нормализованное" значение-указатель с числом свободных парагра- фов (16-байтовых блоков) в старшем слове и счетчиком свободных байт (от 0 до 15) в младшем слове. Следующая функция BlockSize преобразует значение поля Size в обычное значение типа Longint:
function BlockSize(Size: Pointer): Longint; type PtrRec = record Lo, Hi: Word end; begin BlockSize := Longint(PtrRec(Size)).Hi)*16+PtrRec(Size).Lo end;