Если произошла ошибка и возбуждена исключительная ситуация, то она будет обрабатываться по такому алгоритму:
- Если ситуация возникла внутри блока try..except, то там она и будет обработана. Если ИС "продвинута" дальше при помощи оператора raise, а также если она возникла в блоке try..finally, обработка продолжается.
- Если программистом определен обработчик события Application.onException, то он получит управление. Обработчик объявлен следующим образом:
TExceptionEvent = procedure (Sender: TObject; E: Exception) of object;
- Если программист никак не определил реакцию на ИС, то будет вызван стандартный метод ShowException, который сообщит о классе и месте возникновения исключительной ситуации.
Протоколирование исключительных ситуаций
Часто нужно иметь подробный материал для анализа причин возникновения ИС. Разумно было бы записывать все данные о них в файл, чтобы потом прогнозировать ситуацию. Такой подход важен для программ, которые так или иначе будут отчуждены от разработчика: в случае возникновения непредвиденной ситуации это позволит ответить на вопросы "кто виноват?" и "что делать?". В следующем примере предложен вариант реализации протоколирования ИС.
|
|
const LogName: string = 'c:\appexc.log';
procedure LogException;
var fs: TFileStream; m: word;buf: array[0..511] of char;
Begin
if FileExists(LogName) then
m:= fmOpenReadWrite
Else
m:= fmCreate;
fs:= TFileStream.Create(LogName,m);
fs.Seek(0,soFromEnd);
StrPCopy(Buf,DateTimeToStr(Mow)+'. ');
ExceptionErrorMessage(ExceptObject,ExceptAddr,@buf[StrLenfbuf)],SizeOf(Buf)-StrLen(buf));
StrCat(Buf,#13#10);
fs.WriteBuffer (Buf, StrLer.;buf));
fs.Free;
end;
Здесь задачу записи информации об ИС решает процедура LogException. Она открывает файловый поток и пишет туда информацию, отформатированную При помощи уже упоминавшейся функции ExceptionErrorMessage.
В качестве ее параметров выступают значения функций Exceptobject и ExceptAddr. К сформированной строке добавляется время возникновения ИС. Для каждого защищаемого блока кода создаются две вложенные конструкции try…except. Первая, внутренняя — для вас; в ней ИС протоколируется и продвигается дальше. Внешняя — для пользователя; именно в ней проводится анализ типа ИС и готовится сообщение.
В Object Pascal существует и расширенный вариант употребления оператора
raise:
raise окземпляр объекта типа Exception> [at <адрес>]
Естественно, объектный тип должен быть порожден от Exception. To, что в таком типе ничего не переопределено, не столь важно - главное, что в обработчике ИС можно отследить именно этот тип.
ELoginError = class (Exception);
If LoginAttemptsNo > MaxAttempts then raise ELoginError.Create('Ошибка регистрации пользователя');
Конструкция at <адрес> используется для того, чтобы изменить адрес, к которому привязывается возникшая ИС, в пределах одного блока обработки ИС.