- •Обработка исключительных ситуаций в Delphi
- •1 Обработка исключительных ситуаций
- •2 Модель исключительных ситуаций в Delphi
- •3 Синтаксис обработки исключительных ситуаций
- •4 Примеры обработки исключительных ситуаций
- •5 Вызов исключительной ситуации
- •6 Доступ к экземпляру объекта exception
- •7 Процедура Assert
- •8 Предопределенные обработчики исключительных ситуаций
5 Вызов исключительной ситуации
В процедуре C из примера мы уже могли видеть, как должна поступать программа при обнаружении состояния ошибки - она вызывает исключительную ситуацию:
raise ESampleError.Create('Error!');
После зарезервированного слова raise следует код, аналогичный тому, что используется для создания нового экземпляра класса. Действительно, в момент вызова исключительной ситуации создается экземпляр указанного класса; данный экземпляр существует до момента окончания обработки исключительной ситуации и затем автоматически уничтожается. Вся информация, которую нужно сообщить в обработчик ошибки, передается в объект через его конструктор в момент создания.
Почти все существующие классы исключительных ситуаций являются наследниками базового класса Exception и не содержат новых свойств или методов. Класс Exception имеет несколько конструкторов, какой из них конкретно использовать - зависит от задачи. Описание класса Exception можно найти в on-line Help.
6 Доступ к экземпляру объекта exception
До сих пор мы рассматривали механизмы защиты кода и ресурсов, логику работы программы в исключительной ситуации. Теперь нужно немного разобраться с тем, как же обрабатывать возникшую ошибку. А точнее, как получить дополнительную информацию о коде ошибки, текст сообщения и т.п.
Как уже говорилось, при вызове исключительной ситуации (raise) автоматически создается экземпляр соответствующего класса, который и содержит информацию об ошибке. Весь вопрос в том, как в обработчике данной ситуации получить доступ к этому объекту.
Рассмотрим модифицированную процедуру A в нашем примере:
procedure NewA;
begin
writeln('Enter A');
try
writeln('Enter A''s try block');
B;
writeln('After B call');
except
on ESE: ESampleError do writeln(ESE.Message);
on ESomethingElse do
writeln('Inside A''s ESomethingElse handler');
end;
writeln('Exit A');
end;
Здесь все изменения внесены в строку
on ESE: ESampleError do writeln(ESE.Message);
Пример демонстрирует еще одно новшество в языке Delphi - создание локальной переменной. В нашем примере локальной переменной является ESE - это тот самый экземпляр класса ESampleError, который был создан в процедуре C в момент вызова исключительного состояния. Переменная ESE доступна только внутри блока do. Свойство Message объекта ESE содержит сообщение, которое было передано в конструктор Create в процедуре C.
Есть еще один способ доступа к экземпляру exception - использовать функцию ExceptionObject:
on ESampleError do
writeln(ESampleError(ExceptionObject).Message);
7 Процедура Assert
Назначение специализированной процедуры Assert, - помощь в отладке кода и контроле над выполнением программы. Процедура является аналогом
макроса ASSERT, который широко применяется практически во всех программах, написанных с использованием C и C++ и их библиотек.
Синтаксис процедуры Assert:
procedure Assert(expr : Boolean [; const msg: string]);
Процедура проверяет логическое утверждение, передаваемое первым аргументом и, если
это утверждение ложно, то процедура выводит на экран диагностическое сообщение с номером
строки и именем модуля, где расположен вызов этой процедуры, и сообщение пользователя,
которое опционально передается вторым аргументом. Затем Assert принудительно завершает выполнение программы после выдачи соответствующего диагностического сообщения.
Процедура Assert обычно применяется в следующих случаях:
в начале процедуры или функции для проверки правильности переданных аргументов;
в конце работы алгоритма для проверки правильности работы алгоритма;
для проверки правильности выполнения "надежных" функций, то есть тех функций, которые всегда должны выполняться успешно всегда, и их невыполнение рассматривается как фатальная ошибка программы.
В любом из этих случаев невыполнение передаваемого в процедуру Assert условия рассматривается как совершенно неожиданная, фатальная ошибка алгоритма, которой не должно быть ни при каких условиях, и которая не оставляет никаких шансов на дальнейшее правильное выполнение программы.
Директива компилятора $ASSERTIONS ON/OFF позволяет отключить генерацию кода процедуры Assert. Это обычно делается в уже отлаженных, годовых к использованию программах. Пример применения процедуры Assert:
program ShowAsserts;
{$APPTYPE CONSOLE}
uses SysUtils;
{$ENDIF}
type
TStorage = class(TObject)
FData: string;
property Data: string read FData write FData;
end;
procedure ModifyStorage(AStorage: TStorage; const s: string);
begin
Assert(AStorage <> nil, '');
AStorage.Data := s;
end;
var
Storage: TStorage;
begin
Storage := TStorage.Create;
try
ModifyStorage(Storage, 'Hello world');
finally
Storage.Free;
end;
// The following call is buggy and triggers the Assert
ModifyStorage(nil, 'Ooops');
end.