Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Обработка исключительных ситуаций.docx
Скачиваний:
4
Добавлен:
01.05.2025
Размер:
89.53 Кб
Скачать

Защитные конструкции языка Object Pascal

Для работы с объектами исключительных ситуаций существуют специальные конструкции языка Object Pascal— блоки try., except и try. .finally. Они контролируют выполнение операторов, помещенных внутри блока до ключевого слова except или finally. В случае возникновения исключительной ситуации штатное выполнение вашей программы немедленно прекращается, и управление передается операторам, идущим за указанными ключевыми словами. Если в вашей процедуре эти блоки отсутствуют, управление все равно будет передано ближайшему блоку, внутри которого возникла ситуация. А уж внутри VCL их предостаточно.

Хотя синтаксис двух видов блоков похож, но они принципиально отличаются назначением и решаемыми задачами. Поэтому вопрос, какой из них выбрать, не стоит: чтение нижеследующего материала, надеемся, убедит вас в пользе обоих.

Блок try..Except

Для реакции на конкретный тип ситуации применяется блок try..except. Синтаксис его следующий:

try

<Оператор>

<Оператор>

...

except

on EExceptionl do < Оператор обработки ИС типа EExceptionl >;

on EException2 do < Оператор >;

...

else { }

<0ператор> {обработчик прочих ИС}

end;

Выполнение блока начинается с секции try. При отсутствии исключительных ситуаций только она и выполняется. Секция except получает управление в случае возникновения ИС. После обработки происходит выход из защищенного блока, и управление обратно в секцию try не передается; выполняются операторы, стоящие после end.

Если вы хотите обработать любую ИС одинаково, независимо от ее класса, вы можете писать код прямо между операторами except и end. Но если обработка отличается, здесь можно применять набор директив on. .do, определяющих реакцию приложения на определенную ситуацию. Каждая директива связывает ситуацию (on...), заданную своим именем класса, с группой операторов (do...).

U := 220.0;

R := 0;

try

I := U / R;

except

on EZeroDivide do MessageBox('Короткое замыкание!');

end;

В этом примере замена if. .then на try. .except, может быть, не дала очевидной экономии кода. Однако если при решении, допустим, вычислительной задачи проверять на возможное деление на ноль приходится не один, а множество раз, то выигрыш от нового подхода неоспорим — достаточно одного блока try. .except на все вычисления.

При возникновении ИС директивы просматриваются последовательно, в порядке их описания. Каждый тип исключительной ситуации, описанный после ключевого слова on, обрабатывается именно этим блоком: только то, что предусмотрено в нем, и будет являться реакцией на данную ситуацию.

Если при этом обработчик родительского класса стоит перед дочерним, последний никогда не получит управления.

try

i:=l;j:=0;

k:=i div j;

...

except

on EIntError do ShowMessage('IntError');

on EDivByZero do ShowMessage('DivByZero');

end;

В этом примере, хотя в действительности будет иметь место деление на ноль (EDivByZero), вы увидите сообщение, соответствующее родительскому классу EintError. Но стоит поменять две конструкции on. .do местами, и все придет в норму.

Если возникла ситуация, не определенная ни в одной из директив, выполняются те операторы, которые стоят после else. Если и их нет, то ИС считается не обработанной и будет передана на следующий уровень обработки. Этим следующим уровнем может быть другой оператор try..except, который содержит в себе данный блок.

Примечание

Мы детально обсудили, что и как помещают в блок try. .except. Но в ряде случаев можно... не размещать там ничего. Пустой блок применяют, когда хотят просто проигнорировать возникновение некоторых ситуаций. Скажем, у вас в программе предусмотрена некая обработка данных, которая может завершиться неудачно, но это не повлияет на дальнейшую работу, и пользователь может об этом не знать. В этой ситуации вполне уместно изолировать ее в пустом блоке try..except. Важно только не поместить туда больше кода, чем нужно — иначе "с водой можно выплеснуть и ребенка".

Если вы не предусмотрели блоков обработки ИС в своем коде, это не должно привести к аварийному завершению всего приложения. Все места в VCL, где управление передается коду разработчика (в том числе, конечно, все обработчики событий всех компонентов), заключены в такие блоки. Но, увы, в Borland не знают о конкретных проблемах вашей программы, и максимум, что они могут сделать для вас, — это проинформировать о типе и месте возникновения ИС. Стандартная обработка подразумевает вывод на экран панели текстового сообщения (из свойства Exception.Message) с указанием типа ошибки. Можно получить и развернутую информацию с именем модуля и адреса, где она имела место (рис. 3.2).

Рис. 3.2. Типовое окно сообщения об ошибке Для этого нужно вызвать процедуру

procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer);

имеющуюся в модуле SYSUTILS.PAS.

Если предусмотренной вами обработки ИС недостаточно, то можно продолжить ее дальше программно при помощи оператора raise.

Этот оператор уже встречался нам при описании создания пользовательских ИС. Там за ним следовал вызов конструктора ИС. Здесь же конструктор опущен: возбуждаться будет уже существующий объект ИС, приведший нас в блок:

...

sl:= TStringList. Create;

try

s1.LoadFromFile(AFileName);

except

sl.Free;

raise;

end;

...

В этом примере в случае возникновения исключительной ситуации созданный список строк должен быть уничтожен. Сама же обработка предоставляется "вышестоящим инстанциям".