2017-02-15 11 views
1

Я следующий код, который сочетает в себе два байта в массив байтов:Ada: Нарушение «No_Exception_Propagation» - Часть 2

pragma Restrictions (No_Exception_Propagation); 

with Interfaces; use Interfaces; 

procedure No_Propagation is 
    type Byte is new Unsigned_8; 
    type Byte_Array is array (Natural range <>) of Byte; 

    function Concat (Input_1 : Byte; 
        Input_2 : Byte) 
        return Byte_Array 
    is 
     Null_Array : Byte_Array (1 .. 0); 
    begin 
     declare 
     Output : constant Byte_Array := Byte_Array'(Input_1 & Input_2); 
     begin 
     return Output; 
     exception 
     when Constraint_Error => 
      return Null_Array; 
     end; 
    end Concat; 

    A, B : Byte; 
begin 
    A := 5; 
    B := 0; 
    declare 
     C : Byte_Array := Concat(A, B); 
    begin 
     null; 
    end; 
end No_Propagation; 

Когда я компилирую это с:

gnatmake -gnatw.e no_propagation.adb 

Я получаю следующее предупреждение:

no_propagation.adb:16:66: warning: pragma Restrictions (No_Exception_Propagation) in effect 
no_propagation.adb:16:66: warning: "Constraint_Error" may result in unhandled exception 

Q1. Почему я получаю предупреждение о том, что «Constraint_Error» может привести к необработанному исключению, если у меня есть обработчик исключений в блоке declare в функции Concat?

Q2. Как вставить два байта вместе в Byte_Array, создать ошибку Constraint?

+0

Обработчик исключений защищает все после 'begin' - но инициализация перед ним ... Я думаю, вам нужен обработчик перед процедурой' End'. –

ответ

2

Я думаю, что ваш код запуска Чрезмерный энтузиазм предупреждение от GNAT.

Чтобы ответить на вопрос 1, вы увидите немного дальше вниз

no_propagation.adb:20:10: warning: pragma Restrictions (No_Exception_Propagation) in effect 
no_propagation.adb:20:10: warning: this handler can never be entered, and has been removed 

и причина этого заключается в том, что ваш обработчик исключений слишком поздно, как это было предложено @BrianDrummond. Вы пишете

declare 
    Output : constant Byte_Array := Byte_Array'(Input_1 & Input_2); 
    begin 
    return Output; 
    exception 
    when Constraint_Error => 
     return Null_Array; 
    end; 

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

 declare 
     Output : constant Byte_Array := Byte_Array'(Input_1 & Input_2); 
     begin 
     return Output; 
     end; 
    exception 
     when Constraint_Error => 
     return Null_Array; 

, но вы получите то же предупреждение; на этот раз, я думаю, потому что исключение должно быть распространено вне сферы охвата, в которой оно было поднято. Если да, то это, кажется печальное следствие правил, или, возможно, проблема реализации: No_Exception_Propagation является GNAT extension,

Это ограничение гарантирует, что исключения никогда не распространяются на внешнюю область подпрограммы. Единственным случаем, в котором может быть возбуждено исключение, является то, что обработчик статически находится в одной и той же подпрограмме, так что эффект рейза по существу похож на инструкцию goto. Любой другой оператор raise (неявный или явный) будет считаться необработанным. Обработчики исключений разрешены, но не могут содержать идентификатор возникновения исключения (выбор исключения). Кроме того, использование пакета GNAT.Current_Exception не разрешено, а заявления о ререйзе (повышение без операнда) не разрешены.

Что касается вопроса 2, это выглядит как другой компилятор. Byte_Array’(Input_1 & Input_2) вызывает предупреждение, Byte_Array'(Input_1, Input_2) - нет.

В любом случае вы получите такое же предупреждение при вызове Concat.

Наилучший подход, вероятно, состоит в том, чтобы подавить все эти предупреждения, используя -gnatw.X, «отключить предупреждения для нелокального исключения» (предполагается, что это значение по умолчанию, но я думаю, что предупреждения включаются с No_Exception_Propagation).

2

Намного проще версия вашей программы:

------------------------------------------------------------------ 
-- Simpler version of no propogation -- 
------------------------------------------------------------------ 
pragma Restrictions (No_Exception_Propagation); 

with Interfaces; use Interfaces; 

procedure No_Propagation2 is 
    type Byte is new Unsigned_8; 
    type Byte_Array is array (Natural range <>) of Byte; 

    function Concat (Input_1 : Byte; 
        Input_2 : Byte) 
        return Byte_Array 
    is 
    begin 
     return (Input_1, Input_2); 
    end Concat; 

    A : Byte := 5; 
    B : Byte := 0; 
    C : Byte_Array := Concat(A, B); 
begin 
    null; 
end No_Propagation2;