Во всех предыдущих примерах, посвященных обработке исключений, были использованы стандартно определенные исключения Ады.
Обработка исключений определяемых пользователем идентична обработке предопределенных исключений, однако, при этом могут возникать некоторые проблемы с областью видимости.
Рассмотрим следующий пример:
| with Ada.Text_IO; use Ada.Text_IO;
procedure Demo is procedure Problem_In_Scope is Cant_Be_Seen : exception; begin raise Cant_Be_Seen; end Problem_In_Scope; begin Problem_In_Scope; exception when Cant_Be_Seen => Put("just handled an_exception"); end Demo; |
Этот пример не корректен.
Проблема в том, что область видимости исключения Cant_Be_Seen
ограничивается процедурой Problem_In_Scope, которая, собственно и является источником этого исключения.
То есть, исключение Cant_Be_Seen не видимо и о нем ничего не известно за пределами процедуры Problem_In_Scope.
Поэтому, это исключение не может быть точно обработано процедурой Demo.
Решить эту проблему можно использованием опции others в обработчике исключений внешней процедуры Demo:
| with Ada.Text_IO; use Ada.Text_IO;
procedure Demo is procedure Problem_In_Scope is Cant_Be_Seen : exception; begin raise Cant_Be_Seen; end Problem_In_Scope; begin Problem_In_Scope; exception when others => Put("just handled some exception"); end Demo; |
Другая проблема возникает тогда, когда в соответствии с правилами области видимости, исключение, описываемое в одной процедуре, перекрывает (или прячет) исключение, описываемое в другой процедуре:
| with Ada.Text_IO; use Ada.Text_IO;
procedure Demo is Fred : exception; -- глобальное исключение ------------------------------------ procedure P1 is begin raise Fred; end P1; ------------------------------------ procedure P2 is Fred : exception; -- локальное исключение begin P1; exception when Fred => Put("wow, a Fred exception"); end P2; ------------------------------------ begin P2; exception when Fred => Put("just handled a Fred exception"); end Demo; |
|
------------------------------------ procedure P2 is Fred : exception; begin P1; exception when Fred => -- локальное исключение Put("wow, an_exception"); when Demo.Fred => -- "более глобальное" исключение Put("handeled Demo.Fred exception"); raise; end P2; |