11.4. ОБРАБОТКА ИСКЛЮЧЕНИЙ

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

Ссылки: возбуждение исключения 11.3, исключение 11, обработчик исключения 11.2, оператор 5, описание 3.1, предвыполнение 3.1, 3.9.

11.4.1. ИСКЛЮЧЕНИЯ, ВОЗБУЖДАЕМЫЕ ПРИ ВЫПОЛНЕНИИ ОПЕРАТОРОВ

Обработка исключения, возбуждаемого при выполнении последовательности операторов, зависит от того, вложена ли она в самое внутреннее окружение или в оператор принятия. Случай вложенности в оператор принятия описан в разд. 11.5.

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

Если некоторое исключение возбуждено в последовательности операторов окружения, содержащего нужный обработчик, то выполнение этой последовательности операторов прекращается и управление передается обработчику данного исключения. Выполнение последовательности операторов обработчика заканчивает выполнение окружения (или предвыполнение, если окружение — тело пакета).

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

а) Для тела подпрограммы — то же исключение повторно возбуждается в точке вызова этой подпрограммы, кроме случаев, когда она является главной программой. Тогда выполнение главной программы прекращается.

б) Для оператора блока — то же исключение повторно возбуждается непосредственно после оператора блока (т. е. в самом вложенном объемлющем окружении или в операторе принятия, содержащем этот оператор блока).

в) Для тела пакета, являющегося дополнительным элементом описания, — то же исключение повторно возбуждается непосредственно после этого элемента описания (в объемлющем разделе описаний). Если тело этого пакета описано как субмодуль, то исключение повторно возбуждается на месте соответствующего следа тела. Если пакет является библиотечным модулем, то выполнение главной программы прекращается.

г) Для тела задачи — задача становится законченной.

Говорят, что повторно возбужденное исключение (как это рассмотрено в пп. а), б) и в)) распространяется либо выполнением подпрограммы, либо выполнением оператора блока, либо предвыполнением тела пакета. В случае тела задачи распространения не происходит. Если окружение является подпрограммой или оператором блока и если оно содержит зависимые задачи, то распространение исключения происходит только после завершения зависимых задач.

Наконец, если исключение возбуждено в последовательности операторов обработчика исключения, то выполнение этой последовательности операторов прекращается. Последующие действия (включая возможное распространение) зависят от природы окружения и выполняются в соответствии с пп. а) ~ г).

Пример:

function FACTORIAL (N : POSITIVE) return FLOAT isbegin   if N = 1 then       return 1.0;   else      return FLOAT(N) * FACTORIAL(N-I);   end if;exception   when NUMERIC_ERROR => return FLOATSAPE_LARGE;end FACTORIAL;

Если при умножении возбуждается исключение NUMERIC_ERROR, то значение FLOAT'SAFE- LARGE возвращается обработчиком исключения. Это значение будет вызывать возбуждение исключения NUMERIC_ERROR при вычислении выражения в каждом из оставшихся обращений к этой функции. Таким образом, для больших значений N эта функция всегда будет возвращать значение FLOAT'SAFE-LARGE.

Пример:

procedure P is   ERROR : exception;   procedure R;   procedure Q is   begin      R;      ... -— ошибочная ситуация 2       exception      ...      when ERROR => -— обработчик Е2   end Q;   procedure R is   begin      ...  -— ошибочная ситуация З    end R;begin   ...  —- ошибочная ситуация 1   Q;   ...exception   ...   when ERROR =>    -- обработчик Е1    ...end P;

Могут возникнуть следующие случаи:

1. Если исключение ERROR возбуждено при выполнении последовательности операторов внешней процедуры P, то выполнение процедуры Р заканчивает обработчик Е1, расположенный внутри Р.

2. Если исключение ERROR возбуждено при выполнении последовательности операторов процедуры Q, то обработчик Е2, расположенный внутри Q, закончит ее выполнение. По окончании выполнения этого обработчика управление будет возвращено в точку вызова процедуры Q.

3. Если исключение ERROR возбуждено в теле процедуры R, вызываемой из процедуры Q, то выполнение процедуры R прекращается и то же самое исключение возбуждается в теле Q. Затем обработчик Е2 заканчивает выполнение процедуры Q, как и в случае 2.

Заметим, что в случае 3 возбуждение исключения в R приводит (косвенно) к передаче управления обработчику, являющемуся частью Q и, следовательно, не вложенному в R. Заметим также, что если бы внутри R был задан обработчик с выбором others, то в случае 3 вместо непосредственного завершения R выполнился бы этот обработчик.

Наконец, если бы исключение ERROR было описано в R, а не в Р, то обработчики Е1 и Е2 не могли бы обеспечивать обработку исключения ERROR, так как этот идентификатор не был бы видимым внутри тел Р и Q. В случае 3, однако, это исключение могло бы быть обработано в Q с помощью обработчика с выбором исключения others.

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

Предопределенные исключения — это исключения, которые могут распространяться базовыми и предопределенными операциями.

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

Ссылки: базовая операция типа 3.3.3, библиотечный модуль 10.1, вызов подпрограммы 6.4, выполнение 9.4, главная программа 10.1, зависимая задача 9.4, задача 9, исключение 11, исключение NUMERIC_ERROR 11.1, конкретизация настройки 12.3, настраиваемый модуль 12, обработчик исключения 11.2, окружение 11.1, оператор 5, оператор блока 5.6, оператор принятия 9.5, пакет 7, подпрограмма 6, последовательность операторов 5.1, предвыполнение 3.1, 3.9, предопределенная операция 4.5, процедура 6.1, раздел описаний 3.9, след тела 10.2, субмодуль 10.2, тело задачи 9.1, тело пакета 7.1, тело подпрограммы 6.3, элемент описания 3.9.

11.4.2. ИСКЛЮЧЕНИЯ, ВОЗБУЖДАЕМЫЕ ПРИ ПРЕДВЫПОЛНЕНИИ ОПИСАНИЙ

Если исключение возбуждено при предвыполнении раздела описаний данного окружения, то это предвыполнение прекращается. Дальнейшее действие зависит от природы окружения.

а) Для тела подпрограммы — то же исключение повторно возбуждается в точке вызова подпрограммы, кроме случая, когда эта подпрограмма является главной программой, — тогда ее выполнение прекращается.

б) Для оператора блока — то же исключение повторно возбуждается непосредственно после оператора блока.

в) Для тела пакета, являющегося дополнительным элементом описания, — то же исключение повторно возбуждается непосредственно после этого элемента описания в объемлющем разделе описаний. Если тело пакета является субмодулем, то исключение повторно возбуждается на месте соответствующего следа тела. Если пакет является библиотечным модулем, то выполнение главной программы прекращается.

г) Для тела задачи — задача становится законченной, а в точке активизации задачи возбуждается исключение TASKING_ERROR; как пояснено в разд. 9.3.

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

д) Для описания пакета или задачи, являющегося элементом описания, — то же исключение повторно возбуждается непосредственно после этого элемента описания в объемлющем разделе описаний или в спецификации пакета. Для описания библиотечного пакета — выполнение главной программы прекращается.

Говорят, что повторно возбуждаемое исключение (как рассмотрено выше в пп. а) — г)) распространено либо выполнением подпрограммы или оператора блока, либо предвыполнени-ем описания пакета, описания задачи или тела пакета.

Пример исключения в разделе описания оператора блока (случай б}):

procedure P is   ...begin   declare      N: INTEGER := F;  -- ФУНКЦИЯ F может возбуждать исключение ERROR    begin      ...   exception      when ERROR =>    -- обработчик Е1    end;exception   when ERROR =>    -- обработчик Е2end P;-- если исключение ERROR возбуждено в описании N, то -- оно обрабатывается обработчиком Е2

Ссылки: активизация задачи 9.3, библиотечный модуль 10.1, вызов подпрограммы 6.4, главная программа 10.1, задача 9, законченная задача 9.4, исключение 11, исключение TASKING - ERROR 11.1, окружение 11.2, оператор блока 5.6, описание задачи 9.1, описание пакета 7.1, подпрограмма 6, предвыполнение 3.1, 3.9, раздел описаний 3.9, след тела 10.2, спецификация пакета 7.1, субмодуль 10.2, тело задачи 9.1, тело пакета 7.1, тело подпрограммы 6.3, элемент описания 3.9.