Работа с динамической памятью и указателями в системе Turbo Pascal. Мирецкий И.Ю - 11 стр.

UptoLike

Составители: 

ческая переменная, до размещения ее в куче проверяется список свободных блоков. Если есть свободный
блок подходящего размера (размер больше или равен размеру распределяемого блока), то он используется.
Примечание. Процедура Release всегда очищает список свободных блоков, что заставляет монитор
кучи "забыть" о всех свободных блоках, которые могли быть ниже указателя кучи. Если
вызовы Mark и
Release чередуются с вызовами Dispose и FreeMem, то необходимо быть уверенным в том, что таких сво-
бодных блоков нет.
Переменная FreeList (модуль System) указывает на первый
свободный блок в куче. Этот блок содержит указатель на следующий свободный блок, который содержит
указатель на следующий свободный блок и т.д. Последний свободный блок содержит указатель
на верши-
ну кучи (т.е. на положение, указываемое HeapPtr). Если список свободных блоков пуст, FreeList равна
HeapPtr.
Формат первых 8 байт свободного блока определяется типом TFreeRec:
type
PFreeRec = ^TFreeRec;
TFreeRec = record
Next : PFreeRec;
Size : Pointer;
end;
Поле Next указывает на следующий свободный блок, или на то же положение, что и HeapPtr,
если блок - последний свободный блок. Поле Size хранит размер свободного блока. Значение Size это
нормализованное значение
указателя с числом свободных параграфов (16-байтовых блоков) в старшем
слове и числом свободных байт (от 0 до 15) в младшем слове. Функция BlockSize преобразует значение
поля Size в нормальное значение LongInt:
function BlockSize(Size: Pointer): Longint;
type
PtrRec = record Lo, Hi: Word; end;
begin
BlockSize := Longint(PtrRec(Size).Hi) * 16 + PtrRec(Size).Lo;
end;
Чтобы обеспечить место для TFreeRec в начале свободного блока, монитор кучи округляет раз-
мер каждого блока, распределяемого New или GetMem, до 8-байтовой границы. Так, для
блоков, разме-
ром в 1..8 байт распределяется 8 байт, для блоков, размером 9..16 распределяется 16 байт и т. д.
11. Переменная HeapError
Переменная HeapError позволяет установить функцию обработки ошибок кучи, которая вызывает-
ся, когда монитор кучи не может обработать запрос на распределение памяти. HeapError указывает на
функцию со следующим заголовком:
function HeapFunc(Size: Word): Integer; far;
Функция обработки устанавливается присваиванием ее адреса
переменной HeapError:
HeapError := @HeapFunc;
Функция обработки ошибок кучи вызывается, когда New или GetMem не могут обработать за-
прос. Параметр Size содержит размер блока, который не мог быть распределен и функция обработки должна
попытаться освободить блок размером не меньшим этого.
Функция обработки возвращает одно из значений 0, 1 или 2. В
случае 0 будет немедленно возникать ошибка времени выполнения в программе.
В случае 1 вместо аварий-
ного завершения программы New или GetMem возвращают указатель, равный Nil. Наконец, 2 означает ус-
пех и повторяет запрос на распределение памяти (который может опять вызвать функцию обработки оши-
бок).
Стандартная функция обработки ошибок кучи всегда возвращает 0, что приводит к аварийному
завершению программы, если New или GetMem не могут быть выполнены.
ческая переменная, до размещения ее в куче проверяется список свободных блоков. Если есть свободный
блок подходящего размера (размер больше или равен размеру распределяемого блока), то он используется.
         Примечание. Процедура Release всегда очищает список свободных блоков, что заставляет монитор
кучи "забыть" о всех свободных блоках, которые могли быть ниже указателя кучи. Если вызовы Mark и
Release чередуются с вызовами Dispose и FreeMem, то необходимо быть уверенным в том, что таких сво-
бодных блоков нет.
         Переменная FreeList (модуль System) указывает на первый
свободный блок в куче. Этот блок содержит указатель на следующий свободный блок, который содержит
указатель на следующий свободный блок и т.д. Последний свободный блок содержит указатель на верши-
ну кучи (т.е. на положение, указываемое HeapPtr). Если список свободных блоков пуст, FreeList равна
HeapPtr.
         Формат первых 8 байт свободного блока определяется типом TFreeRec:

       type
          PFreeRec = ^TFreeRec;
          TFreeRec = record
             Next : PFreeRec;
             Size : Pointer;
          end;

              Поле Next указывает на следующий свободный блок, или на то же положение, что и HeapPtr,
если блок - последний свободный блок. Поле Size хранит размер свободного блока. Значение Size это
нормализованное значение указателя с числом свободных параграфов (16-байтовых блоков) в старшем
слове и числом свободных байт (от 0 до 15) в младшем слове. Функция BlockSize преобразует значение
поля Size в нормальное значение LongInt:
        function BlockSize(Size: Pointer): Longint;
        type
              PtrRec = record Lo, Hi: Word; end;
        begin
              BlockSize := Longint(PtrRec(Size).Hi) * 16 + PtrRec(Size).Lo;
        end;

         Чтобы обеспечить место для TFreeRec в начале свободного блока, монитор кучи округляет раз-
мер каждого блока, распределяемого New или GetMem, до 8-байтовой границы. Так, для блоков, разме-
ром в 1..8 байт распределяется 8 байт, для блоков, размером 9..16 распределяется 16 байт и т. д.


                                     11. Переменная HeapError
        Переменная HeapError позволяет установить функцию обработки ошибок кучи, которая вызывает-
ся, когда монитор кучи не может обработать запрос на распределение памяти. HeapError указывает на
функцию со следующим заголовком:

       function HeapFunc(Size: Word): Integer; far;

       Функция обработки устанавливается присваиванием ее адреса переменной HeapError:

       HeapError := @HeapFunc;

        Функция обработки ошибок кучи вызывается, когда New или GetMem не могут обработать за-
прос. Параметр Size содержит размер блока, который не мог быть распределен и функция обработки должна
попытаться освободить блок размером не меньшим этого.
        Функция обработки возвращает одно из значений 0, 1 или 2. В
случае 0 будет немедленно возникать ошибка времени выполнения в программе. В случае 1 вместо аварий-
ного завершения программы New или GetMem возвращают указатель, равный Nil. Наконец, 2 означает ус-
пех и повторяет запрос на распределение памяти (который может опять вызвать функцию обработки оши-
бок).
        Стандартная функция обработки ошибок кучи всегда возвращает 0, что приводит к аварийному
завершению программы, если New или GetMem не могут быть выполнены.