Управление памятью в Turbo Pascal



Система программирования Turbo Pascal дает возможность использования памяти обоих типов: код программы и глобальные переменные размещаются в памяти статически, а локальные данные процедур, передаваемые им при вызове параметры и служебная информация, используемая для организации вызова подпрограммы и возврата из нее, - динамически (в стеке программы, автоматически).

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

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

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

Кроме того, все переменные, объявленные в программе, размещаются в одной непрерывной области памяти, называемой сегментом данных. Размер сегмента данных ограничивается архитектурой компьютера, возможностями его адресации (при работе микропроцессора Intel в реальном режиме он составляет 64 Кб). Это также вызывает затруднения при обработке больших массивов данных.

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

Экземпляры динамических переменных размещаются в динамической памяти, предоставляемой программе при ее работе. При работе в MS-DOS (реальный режим работы микропроцессора Intel) эта область составляет всю доступную память (оперативная память в пределах 1 Мб за вычетом памяти, используемой системой, сегмента данных программы (его размер обычно составляет 64 Кб), сегмента стека программы (содержащего собственно код программы, ее тело) и сегмента стека (обычно 16 Кб)), что составляет обычно от 200 до 400 Кб. Параметры распределения памяти для программ на языке Pascal могут быть изменены (размеры областей можно увеличивать или уменьшать).

Для организации работы с динамической памятью используются особые переменные, называемые указателями. Указатель в качестве своего значения содержит адрес первого байта памяти, по которому записывается собственно данные, поэтому указатели называют ссылочными переменными. Указатели могут быть типизированными (они содержат адреса переменных заранее определенного типа, который задается в описании) и нетипизированными (при объявлении указателя он не связывается с каким-либо конкретным типом данных, а его тип описывается типом Pointer). Значения типа Pointer совместимы со всеми другими типами указателей.

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

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

¨ New - создает новую динамическую переменную и устанавливает на нее переменную-указатель;

¨ Dispose - уничтожает динамическую переменную;

¨ GetMem - запрашивает новый блок памяти заданного размера для размещения динамических данных и устанавливает на него переменную-указатель;

¨ FreeMem - освобождает блок памяти заданного размера в куче;

¨ Mark - записывает в переменной-указателе текущее состояние кучи;

¨ Release - возвращает кучу в заданное состояние;

¨ MaxAvail - возвращает размер наибольшего непрерывного свободного блока кучи (блока доступного для распеределния);

¨ MemAvail - возвращает количество имеющихся в куче свободных байтов;

¨ Addr - возвращает адрес заданного объекта;

¨ Cseg - возвращает текущее значение регистра CS;

¨ Dseg - возвращает текущее значение регистра DS;

¨ Ofs - возвращает смещение заданного объекта в сегменте;

¨ Prt - преобразует базовый адрес сегмента и смещение в значение типа указатель;

¨ Seg - возвращает сегмент адреса для заданного объекта;

¨ SPtr - возвращает текущее значение регистра SP;

¨ SSeg - возвращает текущее значение регистра SS.

Основные действия над динамическими переменными - их создание и уничтожение. Процедуры Mark и Release позволяют при работе в реальном режиме облегчить освобождение памяти в куче и избежать ошибок при обходах списков для освобождения занимаемой ими памяти. Перед созданием списка можно запомнить текущее состояние кучи, а после использования списка для освобождения сразу всей памяти, занимаемой его элементами, вместо обхода списка и поэлементного его уничтожения можно просто вернуть кучу к исходному состоянию.

Для присваивания ссылочной переменной значения можно воспользоваться унарной операцией взятия указателя (@). Специальный указатель Nil никуда не указывает (это пустая ссылка), он считается константой, совместимой с любым ссылочным типом.

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

В языке Object Pascal системы программирования Delphi сохранены процедуры Mark и Release, но они считаются “устаревшими” и их использование вызывает ошибки во время выполнения программы.


Дата добавления: 2016-01-05; просмотров: 23; Мы поможем в написании вашей работы!

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






Мы поможем в написании ваших работ!