11.5.6. Обработка ошибок распределения памяти

We use cookies. Read the Privacy and Cookie Policy

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

FUNCTION ИмяФункции( Size : Word ) : Integer;

- 210 -

Обычно ее называют HeapFunc. Эта функция вызывается в случае, когда New или GetMem не может обработать запрос на распределение кучи. Параметр Size содержит размер блока, который не мог быть распределен, и функция обработки ошибки должна попытаться освободить блок размером не меньше Size. В качестве результата функция должна возвращать значения 0, 1 или 2. В случае 0 немедленно будет возникать фатальная ошибка и останов программы. В случае 1 вместо аварийного завершения процедуры New или GetMem будет возвращаться указатель, равный nil. Наконец, 2 означает как бы замалчивание ошибки, но вызывает повторение запроса на распределение, что, впрочем, может опять вызвать ошибку.

Необходимо, чтобы эта функция компилировалась в режиме {$F+}. Функция обработки ошибки (пусть в программе она названа UserHeapFunc) может быть подставлена в монитор кучи присваиванием ее адреса системной переменной HeapError:

HeapError := @UserHeapFunc;

Мало смысла в том, чтобы писать свои функции HeapFunc, возвращающие значение 0. Программа и так оборвется при нехватке памяти в куче. Зато очень удобно обрабатывать ошибки распределения памяти, если установить возвращаемое значение равным 1:

{$F+}

FUNCTION HeapFunc(Size : Word) : Integer;

BEGIN

HeapFunc := 1

END;

{$F-}

и подставить эту функцию через переменную HeapError. Теперь можно анализировать последствия работы любой процедуры размещения динамических переменных:

...

New(P);

if P = nil then обработка ситуации нехватки памяти;

{иначе нормальная работа с P^}

...

Если пойти еще дальше, то можно написать функцию HeapFunc такой структуры:

- 211 -

($F+}

FUNCTION HeapFunc( Size : Word ) : Integer;

BEGIN

{ ОСВОБОЖДЕНИЕ КАКИМ-ЛИБО СПОСОБОМ Size БАЙТ В КУЧЕ }

HeapFunc := 2 {и повтор неудачного распределения }

END;

{$F-}

Начальное значение переменной HeapError при старте программы равно nil. Его же надо восстанавливать, если отпала необходимость в обработке ошибок кучи.