- •Динамическая память.
- •Указатель.
- •Стандартные процедуры размещения и освобождения динамической памяти.
- •1. С помощью стандартной процедуры New:
- •2. С помощью стандартной процедуры GetMem.
- •С помощью стандартной процедуры Dispose
- •С помощью стандартной процедуры fRееМеm.
- •Стандартные функции обработки динамической памяти.
- •Примеры и задачи.
- •Организация списков.
- •Задачи включения элемента в линейный однонаправленный список без головного элемента.
- •Формирование пустого списка.
- •Формирование очередного элемента списка.
- •Подсчет числа элементов списка.
- •Вставка элемента в начало списка.
- •Включение элемента в конец списка.
- •Включение в середину (после I-ого элемента).
- •1.1Задачи на удаление элементов из линейного однонаправленного списка без головного элемента.
- •Удаление элемента из начала списка.
- •Удаление элемента из конца списка.
- •Удаление элемента из середины списка (в данном случае I-ого элемента).
- •Удаление всего списка с освобождением памяти.
- •Задачи на замену элементов в линейном однонаправленном списке без головного элемента.
- •Стеки, деки, очереди.
- •Использование рекурсии при работе со списками.
Стандартные процедуры размещения и освобождения динамической памяти.
При выполнении программы наступает момент, когда необходимо использовать динамическую память, т.е. выделить её в нужных видах, разместить там какие-то данные, поработать с ними, а после того, как в данных отпадет необходимость - освободить выделенную память.
Динамическая память может быть выделена следующими способами:
1. С помощью стандартной процедуры New:
New (P);
где р - переменная типа «типизированный указатель».
Эта процедура:
|
Размер и структура выделяемого участка памяти задается размером памяти для того типа данных, с которым связан указатель P.
Доступ к значению созданной переменной можно получить с помощью обращения вида P^.
2. С помощью стандартной процедуры GetMem.
GetMem ( P, size );
где P - переменная типа «указатель» требуемого типа.
size - целочисленное выражение размера запрашиваемой памяти в байтах, здесь также может использоваться функция SizeOf(тип_данных).
Эта процедура создает новую динамическую переменную требуемого размера и свойства, а также помещает адрес этой созданной переменной в переменную Р типа «указатель». Доступ к значению созданной переменной можно получить с помощью P^.
Например:
type
Rec =record
Field1:string[30];
Field2:integer;
end;
ptr_rec = ^ rec;
var
p : ptr_rec;
begin
GetMem ( Р, SizeOf (Rec)); { Выделение памяти;
адрес выделенного участка фиксируется в Р;
размер этой памяти в байтах определяет и возвращает стандартная функция SizeOf , примененная к описанному типу данных; однако, зная размеры внутреннего представления используемых полей, можно было бы подсчитать размер памяти «вручную» и записать в виде константы вместо SizeOf (Rec) }
...
{использование памяти}
...
FreeMem ( p, SizeOf (Rec)); {освобождение уже ненужной памяти}
...
Динамическая память может быть освобождена следующими способами
С помощью стандартной процедуры Dispose
(употребляется в паре с New(…)).
Dispose (P);
где P - переменная типа «указатель»
(типизированный).
В результате работы процедуры Dispose(P) участок памяти, связанный с указателем P, помечается как свободный для возможных дальнейших размещений. При этом физической чистки указателя P и связанной с ним памяти нe происходит, поэтому, даже удалив этот экземпляр записи, можно все же получить значения ее полей, однако использовать это обстоятельство категорически не рекомендуется.
С помощью стандартной процедуры fRееМеm.
(употребляется в паре с GetMem (…)).
FreeMem (P, size);
где P - переменная типа «указатель»,
size - целочисленное выражение размера памяти в байтах для освобождения.
Эта процедура помечает память размером, равным значению выражения size, связанную с указателем P, как свободную (см. пример для GetMem).
3. Автоматически по завершении всей программы.
Управлять распределением и освобождением оперативной памяти можно следующей парой процедур
Mark (P);
Release (P);
где P - переменная типа «указатель»;
Mark - запоминает в переменной-указателе р состояние
динамической области в данный момент;
Release - освобождает всю динамическую память,
которая выделена процедурами New или Getmem после запоминания текущего значения указателя р с помощью процедуры Mark.
Следует распределять и освобождать память «парными» процедурами:
GetMem – FreeMem,
New – Dispose,
Mark – Release.
Обращения к Mark и Release нельзя чередовать с обращениями к Dispose и Frееmem ввиду различий в их реализации.
Например:
var
p : pointer;
p1, p2, p3 : ^integer;
begin
New (p1);
p1^ := 10;
Mark (p) ; {пометка динамической области}
New (p2) ;
p2^ := 25 ;
New (p3) ;
p3^ := p2^ + p1^;
Writeln ( p3^);
Release (p) ; {память, связанная с p2^ и p3^, освобождена, а p1^ может использоваться}
end.
