TURBO PASCAL

Новости           

Программы

Turbo Pascal

Игры

Документация

"Странности"

FAQ

Ссылки

Гостевая книга

Благодарности

От автора

 

 

 

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

Вся динамическая память в Турбо - Паскале рассматривается как сплошной массив байтов, который называется кучей. Физически куча располагается в старших адресах сразу за областью памяти, которую занимает тело программы:

Системная область

Старшие адреса HEAPEND

Куча

HEAPPTR

Программа

HEAPORG

Системная

область

Младшие адреса

END.

После выполнения процедуры NEW(I) указатель ] приобретает значения, которые имел указатель кучи HEAPPTR, а сам HEAPPTR увеличивает свое значение на величину памяти, выделяемой для переменной, на адрес которой указывает указатель I. Память под любую переменную выделяется порциями, кратными 8 байт.

Для доступа к переменной, адрес которой содержит указатель имеются две возможности:

1 - Использовать идентификатор переменной

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

Первый способ нам известен: мы его использовали раньше.

Во втором способе используется разименование указателя: для того, чтобы по указателю на переменную получить доступ к самой переменной нужно после переменной - указателя поставить символ А. Например: 1Л:=2 - в область памяти I помещено значение 2 RA:=2*PI - в область памяти R помещено значение 6.28

Разименование считается некорректным, если переменная - указатель имеет значение NIL; то есть не существует переменной, на которую ссылается такой указатель. Нетипизированные указатели не могут быть разименованы обычным образом (т. е. как типизированные указатели: 1Л:=2), но могут разименовываться для вычисления адреса (см. раздел "Пример использования большого массива данных" ).

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

RA:=SQRT(RA)+IM7 но:

R:=SQRT(RA)+IA-17 - недопустимо, так как нельзя присваивать указателю вещественное значение

R:=SQRT(R) - недопустимо, таг как нельзя значение указателя возводить в квадрат.

RA:=I - недопустимо, так ках нельзя вещественным данным, на которые указывает указатель, присвоить значение указателя.

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

Для возврата динамической пампк назад в кучу используется процедура DISPOSE(P) , где Р * типизированный указатель. Для нашего примера D1SPOSE(R) и DISPOSER) вернут в кучу тот объем памяти, который был выделен под переменные R

Hi.

Процедура DISPOSE(PTR) не изменяет значение указателя PTR, а лишь возвращает в кучу память, ранее связанную с этим указателем. Однако повторное применение процедуры к свободному указателю приведет к возникновению ошибки периода исполнения. Освободившему» указателю можно присвоить константу NIL (пометить его этой константой) для того, чтобы в дальнейшем определить такой свободный адрес по этой пометке: CONST

1 P:AREAL=NIL:j BEGIN

IF P=NIL THEN NEW(P);

DISPOSE(P);

P:=NIL;

END.

Начальное значение указателя пру. объявлении его в разделе переменных может быть произвольным Поэтому более предпочтительный способ объявления указателя -в виде типизированной константы с одновременным присвоением ему значения NIL.

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

Выделением, освобождением и учетом динамической памяти занимается специальная программа - администратор кучи. Освобождение целого фрагмента кучи: VAR

P1,P2,P3,P4,P5,: INTEGER; BEGIN NE\V(P1) NEW(P2) MARK(P); NEW(P3); NEW(P4); NEW(P5);

RELEASE(P) или DISPOSE(P3) END.

Процедура MARK(P) присваивает переменной - указателю Р текущее значение указателя HEAPPTR. Процедура RELEASE(?) освобождает динамическую память начиная от адреса в указателе Р и до конца кучи:

tmp210-2.jpg

Старшие адреса

Состояние динамической памяти:

a) перед освобождением

b) после Dispose(p3)

c) после Release(p)

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

GETMEM(P,SIZE) - для резервирования

FREEMEM(P,SIZE) - для освобождения, где:

Р- нетипизированный указатель

SIZE - размер в байтах части кучи

Данный процедуры работают аналогично процедурам NEW(P) и DISPOSE(P).

За одно обращение к процедуре GETMEM(P,SIZE) можно зарезервировать не более 65521 байт динамической памяти.

Использование процедур GETMEM(P,SIZE) и FREEMEM(P,SIZE) как и вообще работа с динамической памятью требует особой осторожности и тщательного соблюдения правила: освобождать нужно ровно столько памяти, сколько ее было зарезервировано, и именно с того адреса, с которого она была зарезервирована.

Использование нетипизированных указателей позволяет осуществлять неявное преобразование типов: по одному адресу можно размешать различные типы данных лишь бы они занимали одинаковый объем памяти.

 

На первую страницу

 

Rambler's Top100 PROext: Top 1000 Rambler's Top100
(с)Все права защищены

По всем интересующим вопросам прошу писать на электронный адрес

Hosted by uCoz