На этом шаге мы рассмотрим организацию обработки исключений.
Рассмотрим средства, организующие программную обработку исключений. Их два:
Try <Операторы, способные привести к исключению.> Finally <Операторы, выполняемые в любом случае.> End;
Try <Операторы, способные привести к исключению.> Except <Операторы, выполняемые в случае генерации исключения.> End;
Разница между ними заключается в том, что группа операторов, расположенная между Finally и End, будет выполняться в любом случае, в то время, как операторы, расположенные между Except и End, выполнятся только тогда, когда возникнет исключение.
На уровне модуля можно определить последовательности операторов, которые будут выполняться по одному разу. Для этой цели в модуль добавляются разделы Initialization и Finalization. Раздел Initialization, выполняемый один раз при первом упоминании в программе данного модуля, можно использовать для выделения глобальных ресурсов. Раздел Finalization, выполняемый в конце работы программы, независимо от наличия или отсутствия исключений, можно применять для освобождения глобальных ресурсов.
Приведем общую структуру модуля с указанными разделами:
unit <имя модуля>; interface uses <перечень модулей> <интерфейсная часть модуля>
implementation uses <перечень модулей> <рабочая (скрытая, защищенная) часть модуля> initialization <раздел инициализации> finalization <раздел финализации> end.
При размещении в модуле раздела Finalization надо иметь в виду, что это возможно только при наличии в модуле раздела Initialization.
Остановимся более подробно на обработке исключений в блоках Try...Except.
Наиболее ценным является то, что в разделе Except Вы можете определить тип сгенерированного исключения и обработать его соответствующим образом. Это делается с помощью оператора:
On <класс исключения> Do <оператор>; ,
где класс исключения - это один из классов, приведенных в таблице 1 на шаге 27. Приведем пример использования указанных конструкций:
. . . . . Var A,B,C: ShortInt; . . . . . Try . . . . . C:=StrToInt(Edit1.Text); A:=B div C; . . . . . Except On EConvertError Do MessageDlg ('Вы ввели ошибочное число. Повторите ввод.', mtWarning, [mbOk], 0); On DivByZero Do MessageDlg ('Вы ввели нуль. Повторите ввод.', mtWarning, [mbOk], 0); . . . . . End; . . . . .
Некоторые исключения имеют дополнительные поля (свойства), уточняющие вид ошибки. Например, исключение файлового ввода/вывода EInOutError имеет свойство ErrorCode типа Integer. Чтобы воспользоваться полями исключений, существует следующая форма оператора On:
On <имя>:<класс исключения> Do <оператор>; .
Здесь имя носит локальный характер, нигде не определяется и используется только для того, чтобы можно было сослаться на поле. Приведем пример использования полей (в переменной FileName типа String находится имя файла):
On IO: EIntOutError Do Begin Case IO.ErrorCode Of //Использование имени IO. 2: S:='Файл '+''''+FileName+''''+' не найден'; 3: S:='Ошибочное имя файла '+''''+FileName+''''; 4: S:='Слишком много открытых файлов'; 5: S:='Файл '+''''+FileName+''''+' не доступен'; 100: S:='Достигнут конец файла '+''''+FileName+''''; 101: S:='Диск переполнен при работе с файлм '+''''+FileName+''''; 106: S:='Ошибка ввода при работе с файлом '+''''+FileName+''''; End; MessageDlg (S, mtWarning, [mbOk], 0); End;
В заключение этого раздела разберем последовательность обработки исключений.
Блоки Try...Except могут быть вложенными. Обработка исключений в этих случаях осуществляется следующим образом. При генерации исключений сначала ищется соответствующий ему обработчик On в том блоке Try...Except, где создалась исключительная ситуация. Если он не найден, поиск ведется в обрамляющем блоке Try...Except и т.д. Если поиск не увенчался успехом, то поиск производится на более высоком уровне: в блоке, из которого была вызвана данная подпрограмма и т.д. В случае отрицательного результата выполняется стандартная обработка исключения, заключающаяся в выдаче сообщения о типе исключения.
Как только соответствующий обработчик On найден и выполнен, объект исключения разрушается и управление передается оператору, следующему за тем блоком Try...Except, в котором был осуществлен перехват.
Если в процессе выполнения обработчика исключения возникает исключительная ситуация, то обработка прерывается, прежнее исключение разрушается и генерируется новое исключение. Его обработчик ищется в блоке Try...Except, внешнем по отношению к тому, в котором возникло новое исключение.
На следующем шаге мы познакомимся с преднамеренной генерацией исключений.