Ada:违反 "No_Exception_Propagation" - 第 2 部分

Ada: Violation of "No_Exception_Propagation" - Part 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。当我在 Concat 函数的声明块中有异常处理程序时,为什么我会收到 "Constraint_Error" 可能导致未处理异常的警告?

Q2。将两个字节一起粘贴到 Byte_Array 中如何产生约束错误?

您的程序的一个更简单的版本是:

------------------------------------------------------------------
-- 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;

我认为您的代码触发了来自 GNAT 的 over-enthusiastic 警告。

回答问题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_PropagationGNAT extension

This restriction guarantees that exceptions are never propagated to an outer subprogram scope. The only case in which an exception may be raised is when the handler is statically in the same subprogram, so that the effect of a raise is essentially like a goto statement. Any other raise statement (implicit or explicit) will be considered unhandled. Exception handlers are allowed, but may not contain an exception occurrence identifier (exception choice). In addition, use of the package GNAT.Current_Exception is not permitted, and reraise statements (raise with no operand) are not permitted.

至于问题 2,这看起来像是另一个编译器问题。 Byte_Array’(Input_1 & Input_2) 会导致警告,Byte_Array'(Input_1, Input_2) 不会。

无论哪种情况,您都会在调用 Concat 时收到相同的警告。

最好的方法可能是使用 -gnatw.X、"turn off warnings for non-local exception" 来抑制所有这些警告(这应该是默认设置,但我猜这些警告是通过 [=13= 打开的) ]).