Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Создание и уничтожение динамических переменных




Доступ к переменной по указателю.

Если присваиваем Р1:= @i; то для доступа к переменной i имеется две возможности:

1. Использовать имя i;

2. Используется адрес переменной, который содержится в Р1;

Первый путь, например, i:= i+2;

Для реализации второго, косвенного доступа к переменной через указатель на нее используется конструкция, которая называется разыменованием. Для того чтобы по указателю на переменную получить доступ к самой переменной, необходимо после переменной-указателя поставить значок ‘ ^ ‘.

Например, операторы:

i:= i+2; и P1^:= P1^+2; эквивалентны.

Разыменование, по определению, имеет тип, совпадающий с базовым типом переменной-указателя.

В случае «указателя на указатель» возможно многократное разыменование.

Например, допустима конструкция PP1^^, которая имеет статус целой переменной.

 

Реализуются стандартными процедурами New и Dispose. Процедура New предназначена для создания динамических переменных определенного типа, т.е. для отведения памяти в куче для хранения динамических переменных. Параметром процедуры New является переменная ссылочного типа.

Процедура действует следующим образом:

1. В динамической памяти отводится место для хранения переменной, тип которой совпадает с базовым типом указателя-параметра.

2. Переменной, переданной в параметре, присваивается указатель на отведенную область памяти.

Var

P1: ^integer;

Begin

New(P1);

Фрагмент программы приведет к отведению в куче области памяти и присвоению указателя на эту область переменной Р1.

Доступ к созданной переменной возможен только через указатель Р1: Р1^: = a+b;

Имеется возможность использовать процедуру New в функциональной форме. В качестве параметра функции New задается ссылочный тип, а результатом функции является указатель этого типа.

Type

P = ^integer;

Var

P1: P;

Begin

P1:= New(P);

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

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

Например:

Var

PL: ^longint;

Begin

If MaxAvail >= 4 then New(PL)

else writeln(‘Динамическая память исчерпана’);

В этом фрагменте подразумевается, что переменная типа longint занимает в памяти 4 байта. В более общем случае для определения размера необходимой памяти под переменную можно воспользоваться стандартной функцией SizeOf. Этой функции в качестве параметров передается переменная или тип; ее результатом является число байтов, необходимое данной переменной или переменных данного типа. Функцию SizeOf удобно использовать для составных типов.

Type

Plint = ^ longint;

Var

PL: Plint;

Begin

If MaxAvail >= SizeOf(longint) then

PL:= New(Plint);

Кроме функции MaxAvail, в языке Тurbo Рascal имеется функция MemAvail, которая возвращает суммарный размер всех свободных областей памяти. В общем случае эти функции дают разные результаты. Из-за произвольного характера отведения и освобождения памяти куча может представлять собой случайную последовательность свободных и занятых областей различных размеров.

Функция MaxAvail определяет наибольшую свободную область памяти.

Функция MemAvail определяет общий объем свободных областей.

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

Type

Plint = ^longint;

Var

P:= plint;

Begin

New(P);

Dispose(P);

End.

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

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

Рассмотрим пример:

Program Prim;

Type

Plint = ^longint;

Procedure ABC;

Var

P: Plint;

begin

p:= New(Plint);

end;

Begin

ABC;

End.

Вызов New в процедуре АВС приводит к отведению памяти для динамической переменной типа Plint. После выхода из процедуры АВС по правилам все локальные переменные ПП перестают существовать после ее завершения. Исчезает локальная переменная Р, но область памяти, отведенная в процессе работы ПП АВС, продолжает существовать, т.к. освободить ее можно только посредством процедуры Dispose. После выхода из АВС отсутствует какой-либо доступ к динамической переменной, т.к. указатель Р оказался потерянным при завершении АВС.

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

Рассмотрим пример, когда некоторая область памяти освобождена, а в программе остался указатель на эту область.

Var P: integer;

Procedure A;

Var i: integer;

begin

i:= 12345;

P:= @i;

writeln(P^); {напечатает 12345}

end;

Procedure B;

Var j: integer;

begin

j:= 777;

writeln(P^); {напечатает 777}

end;

Begin

A;

B;

End.

 

Глобальная ссылочная переменная Р первоначально (в процедуре А) устанавливается на локальную переменную i. После завершения процедуры А переменная i исчезает; указатель Р «повисает». Вызов процедуры В приводит к тому, что на место, которое занимала в стеке переменная i, будет помещена переменная j и указатель Р ссылается на нее.

 




Поделиться с друзьями:


Дата добавления: 2014-01-11; Просмотров: 677; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.01 сек.