Решение проблемы утечки ресурсов в блоке try ..Finally

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

Рассмотрим пример утечки ресурсов в случае возникновения исключения: AssignFile (F, 'a.fcmp'); Rawrite (F) ;Hew (P) ;

...// Код., генерирующий исключение Erase (F); Dispose (P);

При возникновении исключения, вычисления в текущем блоке прерываются и управление, в отсутствие обработчика исключения, передается р вышестоящий блок. Таким образом, в случае возникновения исключения, файл не удалится, а

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

использовать специальную конструкцию обработки исключения: try ...finally. Try

«операторы, способные привести к исключению» finally

«операторы, выполняемые в любом случае» end;

В этом случае операторы в разделе finally будут выполняться всегда, независимо от того было исключение или нет. После выполнения этих операторов вычисление прерывается. Например: AssignFile (F, 'a.tmp'); Rewrite (F); New (P) ; try

Код, генерирующий исключение finally

Erase (F) ; Dispose (P); ' end;

В разделе finally неудобно описывать реакцию на исключение, поскольку он не предоставляет механизма доступа к объекту исключения. Поэтому разделы

except, и finally могут использоваться совместно. Например: try try

Код, генерирующий исключение . finally

End; j

Except

end;

Защита кода зачистки на уровне модуля в разделе finalization

Рассмотренный выше блок try...finally позволяет защитить ресурсы внутри блока. Для глобальных ресурсов модуля существует другой способ выделения и инициализации ресурсов, защищенный от утечки ресурсов. Он реализуется с помощью двух специальных включаемых в модуль разделов initialization и finalization. Раздел initialization, выполняемый один раз при первом упоминании в программе данного модуля, можно использовать для однократного выделения необходимых глобальных ресурсов. А раздел finalization, гарантированно выполняемый в конце работы программы независимо от наличия или отсутствия исключений, можно использовать для зачистки ранее выделенных ресурсов.

Например, необходимо после завершения работы программы удалить все файлы *.tmp из каталога dirtmp:

unit .... ;Н

var ь

SR: TSearchRec; F: File;

Result: integer; initialization

Finalization

result := FindFirst (dirtmp + '«.trap', faAnyFile, SR) ; while result = 0 do begin

AssignFile (F, dirtmp+SR.name); Erase <F); result FindNext end;

FindClose (SR); end.

Исключение EAbort ифункция Abort В Delphi имеется исключениеEAbort, несколько отличающееся от рассмотренных ранее. Генерация этого исключения, каки любых других, прерывает процесс вычисления. Но, если приложение не отлавливает оператором on исключений этого класса, то они попадают в обработчик TApplication.HandleException, и там, в отличие от других исключений, разрушаются без всяких сообщений. Таким образом, это исключение - молчаливое прерывание процесса вычисления, при котором не должно отображаться диалоговое окно с сообщением об ошибке.

Простейший путь генерации исключенияEAbort - вызов функцииAbort.

Например:

if «проверка условия прерывания» then Abort;

Обычное применениеEAbort - прерывание вычислений при проверке некоторого условия окончания или прерывания пользователем, что эквивалентно применениюExit иBreak. ОтличиеAbort отExit иBreak заключается в том, чтоBreak прерывает только цикл и управление передается следующему за ним оператору,Exit прерывает только текущую процедуру и передает управление в вызвавшую ее процедуру.Abort прерывает текущую процедуру и все вызвавшие ее процедуры, передавая управление на самый верх. Таким образом, это наиболее простой возврат из глубоко вложенных процедур. Впрочем, можно при необходимости перехватить исключение на каком-то промежуточном уровне, предусмотрев на нем блокtry...except и вставив в его раздел except

соответствующий операторon: on EAbort do ...;

Базовый класс исключений Exception Все предопределенные в Delphi классы исключений являются прямыми или косвенными наследниками классаException, объявленного в модуле SysUtils и наследующего непосредственноTOb ject. Exception = class(TObject) private

Наши рекомендации