Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Praktikum_po_programmirovaniyu.doc
Скачиваний:
23
Добавлен:
09.12.2018
Размер:
2.5 Mб
Скачать

8.3. Основные процедуры и функции для работы с динамическими переменными

Процедура New(r) резервирует фрагмент памяти в куче для размещения новой переменной, причем r – указатель на переменную того типа, который нужно создать. Физически r содержит адрес первого байта памяти, где записана переменная. Сам по себе указатель занимает в памяти всего 4 байта, а данные, на которые он указывает, могут занимать в памяти много килобайт. Каждая отдельная процедура new может разместить только одну динамическую переменную.

Процедура Dispose(r) освобождает участок памяти, занятый объектом с указателем r и помещает адрес освобожденного участка и его длину в список свободных блоков.

Процедура Mark(r) позволяет получить адрес динамически распределенной памяти, соответствующий указателю R.

Процедура Release(R) освобождает всю область динамической памяти, начиная с адреса, полученного в результате выполнения процедуры Mark.

П

роцедура GetMem(r, i) выделяет для динамической переменной байт.

Процедура FreeMem(r, i) освобождает байт динамически распределенной памяти, выделенных процедурой GetMem.

Функция MaxAvail возвращает размер в байтах максимального непрерывного участка свободной памяти в куче. Результат имеет тип LongInt.

Функция MemAvail возвращает размер в байтах общего свободного участка кучи. Результат имеет тип LongInt.

149

8.4. Динамика выделения памяти в куче

Рассмотрим фрагмент программы:

var p1,p2,p3,p4,p5: ^real;

b

egin

new(p1);

new(p2);

mark(p5);

new(p3);

new(p4);

Этому фрагменту программы соответствует следующая структура динамической памяти:

Младшие адреса памяти

Старшие адреса памяти

Процедура Mark () как бы помечает кучу перед размещением динамической переменной , копируя значения текущего указателя кучи () в указатель .

Если выполнить процедуру Release (), то структура кучи будет такой:

150

При этом освобождается вся память, выделенная после обращения к процедуре Mark. Если выполнить Release (HeapOrg), то куча будет очищена полностью, так как указатель HeapOrg содержит адрес начала кучи.

В случае произвольного освобождения динамической памяти удобнее использовать Dispose и FreeMem. При этом, если освобождаемый участок не является последним (верхним) в куче, то куча становится фрагментированной, причем адрес и размер этого свободного участка записывается в список свободных блоков для дальнейшего использования.

Е

сли будет выполнена та же начальная последовательность процедур New, а затем Dispose (), то в середине кучи появится дырка.

151

Если сделать New (), то это опять приведет к выделению той же области памяти. С другой стороны Dispose () увеличивает размер свободного участка, так как и были соседними. Этот свободный участок сольется со свободной памятью кучи, так как последний значащий указатель кучи – это . При этом указатель кучи переместится на первый байт после конца последнего занятого участка, и куча будет находиться в том же состоянии, в каком она была бы при выполнении процедуры Release ():