Программирование на языке Object Pascal

Методическое пособие - Компьютеры, программирование

Другие методички по предмету Компьютеры, программирование

?зм динамической памяти. Динамической считается все оперативная память за вычетом сегмента данных, сегмента стека и сегмента с кодом программы. Память называется динамической, т.к. она выделяется непосредственно в процессе работы программы. Память, расположенная в сегменте данных - статическая и выделяется на этапе компиляции программы.

Динамическая память основана на работе с адресами. При динамическом выделении памяти, заранее не известно: не тип, не количество размещаемых данных. В динамической памяти нельзя обращаться по именам, а только по адресам.

 

Адреса и указатели

 

Операционная память представляет собой совокупность элементарных ячеек для хранения информации. Каждая ячейка может хранить один байт информации и обладает уникальным номером, который называется адресом.

Указатель - переменная, которая в качестве своего значения содержит адрес байта памяти:

 

p: pointer;[@]

 

В ПЭВМ адреса задаются совокупностью двух шестнадцатеричных слов:

. первое слово - сегмент;

. второе слово - смещение.

 

 

Структура адреса ячейки на примере 20-и разрядной адресации:

 

 

Объявление указателей

 

Существует два типа указателей:

1.типизированные (связываются с некоторым типом данных);

2.не типизированные (просто хранят адрес определенного участка памяти). Указатели объявляются в разделе описания переменных и в разделе описания типов (Type и Var).

Объявление типизированных указателей.

 

имя: ^название типа;

Var: ^integer;: ^real;

...=^PersonRecord;=Record;: string [20];: byte;: PersonPeinter;;

В OPascal любой идентификатор или тип, перед его использованием должен быть предварительно объявлен (исключение сделано только для указателей, которые могут ссылаться на еще не объявленный тип данных). Это связано с тем, что динамическая память дает возможность организовывать данные в виде списка.

Объявление не типизированных указателей.

 

имя: painter;

Var: painter;,p2: ^byte;[1 байт]3,p4: ^real;[8 байт]

 

Типизированные и не типизированные указатели хранят значение адресов, однако, значение одного указателя не всегда можно передавать другому. В OPascal передавать значение можно только между указателями, которые связаны с одним и тем же типом данных, исключение составляют не типизированные указатели, которые совместимы со всеми типами данных.

 

Var: painter;,p2: ^byte;,p4: ^real;

...:=p2;:=p4;1:=p3;

p4:=p2;

p1:=p1;

p3:=p;

Обнуление указателя

 

p:=Nil; - после выполнения этой операции указатель продолжает занимать место в памяти, но указывает в никуда (т.е. ни на одну ячейку).

 

p:=Nil;

 

Выделение и высвобождение динамической памяти

 

Вся динамическая память в OPascal рассматривается как сплошной массив байт, который называется куча (HEAP). Физически она располагается в старших адресах памяти сразу за областью, которую занимает код программы.

 

 

При работе с кучей используются стандартные, объявленные по умолчанию переменные:

1.HeapOrg - хранит адрес начала кучи;

2.HeapEnd - хранит адрес конца кучи;

3.HeapPTR - хранит адрес начала незанятого участка кучи.

Выделение в памяти для типизированных указателей осуществляется с помощью процедуры New (имя указателя):

Var

p: ^byte;

New(p);

p^:=2;

 

1.Администратор кучи просматривает ее содержимое и если есть свободный байт - выделяет его, а адрес этого байта записывается в переменную (p).

2.Запись числа (2) в свободное место с адресом (p).

p^ - разадресация указателя, т.е. обращение к значению хранящемуся по адресу, который лежит в (p).

Процедура New выделяет динамическую память для требуемого указателя и только после этого указатель можно использовать. Указатели можно использовать только в операциях соответствующего типа, т.е. в операциях с адресами.

Разадресованные указатели могут использоваться в любых выражениях и операциях:

 

Var:^byte;:real;(p);^:=2;:=SQRT(p^)+2*p^/3

 

Высвобождение динамической памяти.

После использования динамических переменных, память занятую ими необходимо высвободить, для этого используется процедура dispose(имя указателя):

 

Dispose(p);

 

После процедуры dispose указателю снова можно выделить память.

После процедуры dispose значение переменной высвобождается, а указателю присваивается значение Nil.

При работе с указателями ответственность за высвобождение памяти ложится на программиста, т.к. Pascal при завершении работы приложения, самостоятельно занятую память не высвобождает, это может привести к утеске динамической памяти.

Для не типизированных указателей выделение памяти осуществляется процедурой: GetMem (имя указателя, размер). Размер - количество байт, которые будут помечены как занятые. Он может быть от 1 до 65535 байт.

Высвобождение памяти для не типизированных указателей:

 

FreeMem (имя указателя, размер);

 

Пример:

 

Var: pointer;

…(p,400);

FreeMem (p,400);

Процедуры для высвобождения динамической памяти:

Mark (p) - запоминает адрес указателя (p);

Release (p) - высвобождает динамическую память начиная от адреса хранящегося в (p) до конца кучи.

Эти процедуры могут применяться к типизированным и не типизированным указателям.

Пример:

, p2, p3, p4, p5: ^integer;(p1);(p2);(p3);(p4);(p5);

 

Процедуры и функции для работы с динамической памятью:

Addr(x): pointer; - функция возвращает результат типа pointer в котором содержится адрес аргумента (x