моменту блоков. Выдаваемое MaxAvail значение имеет смысл размера наибольшей сплошной структуры данных (как массив, запись, объект), которая могла бы уместиться в куче. Правда, такая сплошная структура данных сама ограничена размером в 65520 байт.
Полный объем свободного пространства (памяти) в куче можно опросить функцией MemAvail. Она вернет сумму длин всех свободных блоков в куче: и освобожденных, и еще ни разу не использованных.
Эти две функции полезны при анализе ресурсов памяти перед размещением динамических переменных, особенно процедурой GetMem. На рис. 11.6 показан пример их использования.
| >PROGRAM TestHeap; {ПРОГРАММА, АНАЛИЗИРУЮЩАЯ МЕСТО В КУЧЕ}
| TYPE
| > Dim = Array [1..5000] of LongInt; { базовый тип }
| VAR
| > P : ^Dim; { ссылка на базовый тип — массив }
| > Psize : LongInt; { переменная для анализа размера }
| CONST
| > SL = SizeOf(LongInt); { размер элемента массива }
| BEGIN
| > WriteLn( 'В куче свободно ', MemAvail, ' байт' );
| >{Psize округляется до целого числа значений LongInt:}
| > Psize := SL*(MaxAvail div SL);
| >if SizeOf(Dim) > Psize
| >then begin { мало места в куче }
| > WriteLn('Массив P^ не может быть размещен целиком');
| > GetMem( P. Psize ); { отводим Psize байт }
| > WriteLn( ' Размещено ', Psize div SL, ' элементов' )
| >end
| >else begin { достаточно места }
| > New( P ); { размещаем массив }
| > Psize := SizeOf(Dim); { объем массива P^ }
| > WriteLn( 'Динамический массив P размещен' )
| >end;
| >{ ... работа с динамическим массивом ... }
| > FreeMem(P, Psize);{универсальное освобождение массива}
| END.
Рис. 11.6
11.5.5. Более детальный анализ состояния кучи
Этот подраздел посвящен детальному разбору механизма ведения учета свободных блоков в куче, и может быть опущен при ознакомительном чтении без потерь для целостности изложения.
- 206 -
При использовании процедур Dispose и FreeMem куча становится фрагментированной, т. е. в ней появляются свободные блоки. Эти блоки могут возникать в любом порядке и со временем куча может превратиться в подобие решета. Но работоспособность кучи не исчезнет.
Адреса и размеры свободных блоков сохраняются в так называемом списке свободных блоков, который имеет стековую структуру и растет сверху вниз от верхней границы области кучи навстречу указателю заполнения кучи HeapPtr. При попытке размещения динамической переменной осуществляется просмотр списка свободных блоков. Если найден свободный блок подходящего размера, то именно он и используется.
Указатель на список свободных блоков хранится в предопределенной системной переменной FreePtr типа Pointer. Эта переменная фактически указывает на массив записей типа FreeList, т.е. соответствует типу FreeListP: