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

Ссылочный тип в языке Pascal

Работа с динамическими величинами связана с использованием еще одного типа данных — ссылочного типа. Величины, имеющие ссылочный тип, называют указателями.

Указатель — это статическая переменная, которая предназначена для хранения адреса переменной, в том числе и адреса динамической переменной в Heap-области. В памяти любой указатель занимает фиксированный объём памяти — 4 байта: 2 слова: 1-ое слово — сегмент памяти, 2-ое слово — смещение.

Адрес — это номер первого байта поля памяти, в котором располагается величина.

Значение указателя — это беззнаковое целое, оно сообщает о том, где размещается переменная, и ничего не говорит о самой переменной. Значением может быть константа nil, в таком случае указатель никуда не ссылается, т.е. пуст. Это можно себе представить таким образом: в адресном пространстве оперативной памяти, выделяется один адрес, по которому заведомо не может быть размешена никакая переменная. На это место в памяти и ссылается такой пустой, или «нулевой» (0000:0000), указатель nil (зарезервированное слово). Это значение можно присваивать любому указателю.

Начало кучи хранится в стандартной переменной HeapOrg, конец - в переменной HeapEnd. На текущую границу незанятой динамической памяти ссылается указатель HeapPtr.

Замечание: ввод/вывод значения указателя не возможен!

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

Указатели

Типизированные

Нетипизированные

Типизированные указатели

Типизированные указатели - указатели, которые ссылаются на область данных фиксированного типа.

Для описания используется символ ^.

Схема объявления указателя:

<имя переменной-указатемя>: ^<базовый тип данных>.

Например, описание Р: ^Integer определяет указатель на динамическую целочисленную переменную.

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

Примеры объявления указателей:

Туре

Mass=array[1..100] of Integer;

p=^integer;

Var

p1: p;

i: integer;

p2: ^Integer;

p3: ^String;

pMass: ^Mass;

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

NEW(<переменная-указатемь>) .

Например, New(p1).

Для освобождения памяти от данных, потребность в которых отпала, имеется стандартная процедура Dispose. Формат обращения к этой процедуре:

DISPOSE(<указатель>) ;

Например, если динамическая переменная, связанная с указателем p1, больше не нужна, то оператор Dispose(p1) пометит область, использованную под переменную p1, как свободную. Особенно существенным становится эффект экономии памяти при удалении больших массивов.

Чередование обращений к New и Dispose обычно приводит к фрагментации — образованию ячеистой структуры памяти. При очередном обращении к New отыскивается наименьший свободный фрагмент, в котором может поместиться переменная.

С целью освобождения целого фрагмента кучи, перед началом выделения динамической памяти текущее значение указателя на границу незанятой динамической памяти запоминается в переменной указателе с помощью процедуры MARK (< переменная-указатель>). Чтобы освободить фрагмент кучи используется процедура RELEASE (<указатель>).

var

р, p1, р2: ^Integer;

Begin

New(p1);

Mark(p);

New(p2);

Release (p);

Dispose(p1);

Dispose(p2);

End.

Замечания:

!следует освобождать выделенные области сразу же после того, как необходимость в них отпадает. Иначе, происходит «засорение» памяти.

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

! после выполнения Dispose указатель на освобождённую область памяти не обнуляется, т.е. значение остаётся доступным в программе сохраняется возможность доступа к формально уже недоступной области, которая к моменту такого ошибочного доступа уже может быть опять выделена для других целей очередным обращением к New.

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

procedure someProc;

var а: integer;

р: ^string;

begin

new(p);

...

end;

Begin

writeln(memAvail);

someProc;

writeln(memAvail);

readln;

End.

Т.о. исчезает локальная переменная p, но область памяти, отведенная под нее, остается так как освободить ее можно только явно - через Dispose.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]