Решение проблемы утечки ресурсов в блоке 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