Студопедия  
Главная страница | Контакты | Случайная страница

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

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

Читайте также:
  1. Архитектура ПК. Центральные и периферийные устройства, средства ввода и средства вывода данных. Оперативная память и средства внешней памяти. Характеристики процессора.
  2. Виды и типы памяти. Воспроизведение. Забывание как психологическая проблема. Кривая забывания Эббингауза. Позиционная кривая воспроизведения.
  3. Вопрос 24. Электронные таблицы Exсel. Автозаполнение. Выделение фрагментов. вставка и удаление строк и столбцов. Создание создание перенос и копирование формул.
  4. Вопрос 5. Законы памяти. Мнемотехнические приемы запоминания
  5. Выделение данных.
  6. Выделение дискового пространства пользователям.
  7. Выделение записей
  8. Выделение льготного кредита из бюджета.
  9. ВЫДЕЛЕНИЕ ПРОБЛЕМЫ ИЗ ВНЕШНЕЙ СРЕДЫ

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

Адрес начала кучи хранится в переменной HeapOrg, конец – в FreePtr, текущая граница не занятой динамической памяти хранится в HeapPtr.

Для выделения памяти под любую переменную используется процедура New, единственным параметром которой является типизированный указатель.

Пример:

Var

I,j: ^Integer;

R: ^Real;

Begin

New(I); New(R);

После выполнения New(I) указатель I приобретает значение, которое имел перед этим текущий указатель границы HeapPtr. Сам указатель HeapPtr увеличивает свое значение на 2, так как длина внутреннего представления типа Integer равна 2 байтам. New(R) вызовет смещение на 6 байт.

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

I^:=2;

R^:=2*Pi;

Допускается, например, R^:=Sqr(R^)+I^-17. Но совершенно недопустимо: R:= Sqr(R^)+I^-17, так как указателюR нельзя присвоить значение вещественного выражения.

Динамическую память можно (и рекомендуется) возвращать в кучу: Dispose(R); Dispose(I) – вернет в кучу 8 байт, ранее взятых.

Процедура Dispose(Ptr) не изменяет значения указателя Ptr, а лишь возвращает в кучу память, ранее связанную с этим указателем. Однако, повторное применение процедуры к «свободному» указателю приведет к возникновению ошибки периода исполнения. Чтобы пометить освободившийся указатель, можно использовать Nil.

Const

P:^Real=Nil;

…….

If P=Nil then

New(P);

Dispose(P);

P:=Nil;

Следует учесть, что начальное значение указателя при его объявлении в разделе переменных может быть произвольным. Использование указателей, которым не присвоено значение процедурой New или каким-либо другим способом, никак не контролируется системой и может привести к непредсказуемым результатам.

Чередование New и Dispose обычно приводит к «ячеистой» структуре памяти.

Существует еще одна возможность для освобождения целого фрагмента кучи. Перед выделением памяти текущее значение указателя HeapPtr запоминается с помощью процедуры Mark. Теперь можно в любой момент освободить фрагмент кучи от этого адреса до конца кучи с помощью процедуры Release.

Var

P, P1, P2, P3, P4, P5:^Integer;

Begin

P1^
P2^
P3^
P4^
P5^
 
 

New(P1);

New(P2);

Mark(P);

New(P3);

New(P4);

New(P5);

Release(P);

 

 

P1^
P2^
 
P4^
P5^
 
 

 

 

Dispose (P3)

 

 

P1^
P2^
 
 
 
 
 

 

 

Release(P)

 

 

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

Для нетипизированных указателей:

GetMem(P,Size) – резервирование памяти

FreeMem(P,Size) –освобождение памяти

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

Size – размер запрашиваемой или освобождаемой кучи в байтах.

При работе с GetMem и FreeMem требуется осторожность: освобождать нужно ровно столько памяти, сколько было запрошено

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

Некорректное использование New и Dispose также может привести к ошибкам:

Var

I,J:^Integer;

R:^Real;

Begin

New(I); {I:=HeapOrg; HeapPtr:= HeapOrg +2}

J:=I; {J:=HeapOrg }

J^:=2;

Dispose(I); {HeapPtr:= HeapOrg }

New(R); {R:= HeapOrg; HeapPtr:= HeapOrg }

R^:=Pi;

WriteLn(J^);

End.

Что будет выведено на экран дисплея? На экране появятся символы 8575, так как J^ будет рассматривать только 2 байта внутреннего представления числа Pi и будет интерпретировать их как представление целого числа.




Дата добавления: 2015-04-12; просмотров: 25 | Поможем написать вашу работу | Нарушение авторских прав

1 | <== 2 ==> | 3 | 4 | 5 |


lektsii.net - Лекции.Нет - 2014-2024 год. (0.007 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав