Проблемы с областью видимости при обработке исключений определяемых пользователем
Во всех предыдущих примерах, посвященных обработке исключений, были использованы стандартно определенные исключения Ады.
Обработка исключений определяемых пользователем идентична обработке предопределенных исключений, однако, при этом могут возникать некоторые проблемы с областью видимости.
Рассмотрим следующий пример:
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; |
Выводом такой процедуры будет "just handled a Fred exception". Исключение, обрабатываемое в процедуре P2, будет локально описанным исключением. Такое поведение подобно ситуации с областью видимости обычных переменных.
Для решения этой проблемы, процедуру P2 можно переписать следующим образом:
------------------------------------ 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; |
выдаст сообщение "handeled Demo.Fred exception" и, с помощью инструкции raise, осуществит передачу исключения Demo.Fred в обработчик исключения процедуры Demo, который, в свою очередь, выдаст сообщение "just handled a Fred exception".