Процедуры и функции для работы с динамической памятью.




Ниже приводится описание как уже рассмотренных процедур и функций, так и некоторых других, которые могут оказаться полезными при обращении к динамической памяти. Функция addr. Возвращает результат типа POINTER, в котором содержится адрес аргумента. Обращение: ADDR (X) Здесь х — любой объект программы (имя любой переменной, процедуры, функции). Возвращаемый адрес совместим с указателем любого типа. Отметим, что аналогичный результат возвращает операция.

Функция CSEG. Возвращает значение, хранящееся в регистре cs микропроцессора (в начале работы программы в регистре содержится сегмент начала кода программы). Обращение: CSEG Результат возвращается в слове типа WORD Процедура DISPOSE. Возвращает в кучу фрагмент динамической памяти, который ранее был зарезервирован за типизированным указателем. Обращение: DISPOSE(TP) Здесь ТР типизированный указатель. При повторном использовании про- процедуры применительно к уже освобожденному фрагменту возникает ошибка периода исполнения. При освобождении динамических объектов можно указывать вторым параметром обращения к DISPOSE имя деструктора.

Функция DSEG. Возвращает значение, хранящееся в регистре DS микропроцессора (в начале работы программы в регистре DS содержится сегмент на- начала данных программы). Обращение: DSEG Результат возвращается в слове типа WORD 16й Часть I Ядро Турбо Паскаля Процедура ffeemem. Возвращает в кучу фрагмент динамической памяти, кото- который ранее был зарезервирован за нетипизированным указателем. Обращение: FREEMEM (P, SIZE) Здесь:? р — нетипизированный указатель;? SIZE — длина в байтах освобождаемого фрагмента.

При повторном использовании процедуры применительно к уже освобожденному фрагменту возникает ошибка периода исполнения. Процедура getmem. Резервирует за нетипизированным указателем фрагмент динамической памяти требуемого размера. Обращение: GFTMFM (P, ST7F) За одно обращение к процедуре можно зарезервировать не более 65 521 байт динамической памяти. Если нет свободной памяти требуемого размера, воз- возникает ошибка периода исполнения.

Если память не фрагментирована, последовательные обращения к процедуре будут резервировать последователь- последовательные участки памяти, так что начало следующего будет располагаться сразу за концом предыдущего. Процедура MARK Запоминает текущее значение указателя кучи HEAPPTR Об- Обращение: MARK (PTR) Здесь PTR — указатель любого типа, в котором будет возвращено текущее значение HEAPPTR Используется совместно с процедурой RELEASE для освобождения части кучи.

Функция maxavail. Возвращает размер в байтах наибольшего непрерывного участка кучи. Обращение: MAXAVAIL Результат имеет тип LONGINT За один вызов процедуры NEW или GETMEM нельзя зарезервировать памяти больше, чем значение, возвращаемое этой функцией. Функция mema VAIL. Возвращает размер в байтах общего свободного пространства кучи. Обращение: MEMAVAIL Результат имеет тип LONGINT Процедура NEW. Резервирует фрагмент кучи для размещения переменной. Обращение: NEW (TP) Здесь тр — типизированный указатель.

За одно обращение к процедуре можно зарезервировать не более 65 521 байт динамической памяти. Если нет свободной памяти требуемого размера, возникает ошибка периода исполнения. Если память не фрагментирована, последовательные обращения к процедуре будут резервировать последователь – последовательные участки памяти, так что начало следующего будет располагаться сразу за концом предыдущего. Процедура NEW может вызываться как функция. В этом случае параметром обращения к ней является тип переменной, размещаемой в куче, а функция NEW возвращает значение типа "указатель". Например: type Pint -ЛInteger; var р: Pint; begin p = New (Pint); end.

При размещении в динамической памяти объекта разрешается в качестве второго параметра обращения к NEW указывать имя конструктора (см. главу 10). Функция OFS. Возвращает значение типа WORD, содержащее смещение адреса указанного объекта. Вызов: OFS (X) Здесь х — выражение любого типа или имя процедуры. Функция PTR. Возвращает значение типа POINTER по заданному сегменту SEG и смещению OFS. Вызов: PTR (SEG, OFS) Здесь: О SEG — выражение типа WORD, содержащее сегмент;? OFS — выражение типа WORD, содержащее смещение.

Значение, возвращаемое функцией, совместимо с указателем любого типа. Процедура RELEASE. Освобождает участок кучи. Обращение: RELEASE (PTR) Здесь PTR — указатель любого типа, в котором предварительно было сохранено процедурой MARK значение указателя кучи. Освобождается участок кучи от адреса, хранящегося в PTR, до конца кучи. Одновременно уничтожается список всех свободных фрагментов, которые, возможно, были созданы процедурами DISPOSE ИЛИ FREEMEM. Функция SEG.

Возвращает значение типа WORD, содержащее сегмент адреса указанного объекта. Вызов: SEG (X) Здесь х — выражение любого типа или имя процедуры. Функция SIZEOF. Возвращает длину в байтах внутреннего представления указанного объекта. Вызов: SIZEOF (X) Здесь х — имя переменной, функции или типа. Например, везде в программе из примера 6.1 вместо константы SIZEOFREAL можно было бы использовать обращение SIZEOF (REAL) 6.7. Администратор кучи

Как уже отмечалось, администратор кучи — это служебная подпрограмма, которая обеспечивает взаимодействие пользовательской программы с кучей. Администратор кучи обрабатывает запросы процедур NEW, getmem, DISPOSE, FREEMEM и др. и изменяет значения указателей HEAPPTR и FREELIST. Указа- Указатель HEAPPTR содержит адрес нижней границы свободной части кучи, а ука- указатель FREELIST — адрес описателя первого свободного блока. В модуле SYSTEM указатель FREELIST описан как POINTER, однако фактически он указывает на следующую структуру данных: type PFreeRec = "TFieeRac; TFreeRec - record Next: pointer; Size: pointer end, Эта списочная структура предназначена для описания всех свободных блоков па- памяти, которые расположены ниже границы HEAPPTR.

Происхождение блоков связано со случайной последовательностью использования процедур NEW—DISPOSE или GETMEM— FREEMEM ("ячеистая" структура кучи). Поле NEXT в записи TFREEREC содержит адрес описателя следующего по списку свободного блока кучи или ад- адрес, совпадающий с HEAPEND, если этот участок последний в списке. Поле SIZE содержит ненормализованную длину свободного блока или 0, если ниже адреса, содержащегося в HEAPPTR, нет свободных блоков., Ненормализованная длина оп- определяется так: в старшем слове этого поля содержится количество свободных параграфов, а в младшем — количество свободных байтов в диапазоне 0—15.

Следующая функция преобразует значение поля SIZE в фактическую длину свобод- свободного блока: Function BlockSizelSize: pointer): Longint; {Функция преобразует ненормализованную длину свободного блока в байты} type PtrRec = record Lo, Hi: word end; var LengthBlock: Longmt; begin BlockSize:= Longlnt(PtrRec(Size).Hi)*16 + PtrRec(S.ze).Lo end; Сразу после загрузки программы указатели heabptr и E'REELIST содержат один и тот же адрес, который совпадает с началом кучи (этот адрес содер- содержится в указателе HEAPORG) При этом в первых 8 байтах кучи хранится за- запись, соответствующая типу TFREEREC (поле NEXT содержит адрес, совпа- совпадающий со значением HEAPEND, а поле SIZE — ноль, что служит дополнительным признаком отсутствия "ячеек" в динамической памяти). При работе с кучей указатели HEAPPTR и FREELIST будут иметь одинаковые значения до тех пор, пока в куче не образуется хотя бы один свободный блок ниже границы, содержащейся в указателе HEAPPTR.

Как только это произойдет, указатель FREELIST станет ссылаться на начало этого блока, а в первых 8 байтах освобожденного участка памяти будет размещена запись TFREEREC Используя FREELIST как начало списка, программа пользователя всегда сможет просмотреть весь список свободных блоков и при необходимости модифицировать его. Описанный механизм вскрывает один не очень существенный недостаток, связанный с работой администратора кучи, а именно: в любой освободившийся блок администратор должен поместить описатель этого блока, а это означает, что длина блока не может быть меньше 8 байт. Администратор кучи всегда выцеляет память блоками, размер которых кратен размеру записи TFREEREC, т. е. кратен 8 байтам. Даже если программа запросит 1 байт, администратор выделит ей фактически 8 байт. Те же 8 байт будут выделены при запросе 2, 3,..., 8 байт; при запросе 9 байт будет выделен блок в 16 байт и т. д.

Это обстоятельство следует учитывать, если вы хотите минимизировать возможные потери динамической памяти. Если запрашиваемый размер не кратен 8 байтам, в куче образуется "дырка" размером от 1 до 7 байт, при- 17Q Часть I. Ядро Турбо Паскаля чем она не может использоваться ни при каком другом запросе динамической памяти вплоть до того момента, когда связанная с ней переменная не будет удалена из кучи. Если при очередном обращении к функции NEW или GETMEM администратор не может найти в куче нужный свободный блок, он обращается к функции, адрес которой содержит переменная HEAPERROR

Эта функция соответствует следующему процедурному типу: type HeapErrorFun = function (Size: word): Integer; Здесь SIZE — размер той переменной, для которой нет свободной динамической памяти. Стандартная функция, адрес которой при запуске программы содержит переменная heaperror, возвращает 0, что приводит к останову программы по ошибке периода счета с кодом 203 (см. приложение 3). Вы можете переопределить эту функцию и таким образом блокировать останов программы. Для этого необходимо написать собственную функцию и поместить ее адрес в указатель HEAPERROR. Например: Function HeapFunc(SlZe: Word): Integer; far; begin HeapFunc:= 1 end; begin {Основная программа) HeapError:= @HeapFunc; end.

Отметим, что функция типа HEAPERRORFUN вызывается только в том случае, когда обращение с требованием выделения динамической памяти было не- неуспешным. Она может возвращать одно из трех значений:? 0 — прекратить работу программы; 0 1 — присвоить соответствующему указателю значение NIL и продолжить работу программы; 0 2 — повторить выделение памяти; разумеется, в этом случае внутри функции типа HEAPERRORFUN необходимо освободить память нужного размера.


Список литературы

1. Бройдо В.Л. Теория информации. Учебное пособие.- 2-е изд.- СПб: Питер, 2005.- 702с.

2. Под ред. А.Д.Урсула. История Прикладная теория информации Учебное пособие. СПб: РАГС, 2006.- 433 с.

3. Под ред. А.Д.Хомоненко Основы современных компьютерных технологий: Учебник/ - СПб: Корона принт, 2009.- 672 с.

4. М.: ФАИР-ПРЕСС Организация информационного производства: Учебное пособие.-, 2005.- 247 с..-(Специальный издательский проект для библиотек)

5. Петров Ю.П. Оперативная память. / Ю.П.Петров.- СПб: БХВ-Петербург, 2005.- 441 с.-(Учебное пособие)

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-12-18 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: