“应”时未引发Ada CONSTRAINT_ERROR

che*_*cks 5 exception ada gnat

我一直在浏览本Ada 95教程。我读到的是,可以定义一个范围与标准范围不同的类型,如果程序试图超出该范围,则将引发错误。在我自己的程序上工作时,我注意到,如果定义中范围的末尾落在其基础类型的边界上,那么当分配超出该范围的值时,程序将不会提高CONSTRAINT_ERROR。取而代之的是它将快乐地继续前进,然后环绕。我编写了一个程序来明确显示这一点。

有人知道解释这种行为的Ada规则吗?

-柯克

这是我终端的输出,源代码在下面。

me@acheron:~/Dropbox/programs/ada$ gnatmake constraints.adb -f
gcc-4.6 -c constraints.adb
gnatbind -x constraints.ali
gnatlink constraints.ali
me@acheron:~/Dropbox/programs/ada$ ./constraints

Type ON has size:           7
It has a min/max of:           0        127
It's base has a min/max of:        -128        127

Type UNDER has size:           7
It has a min/max of:           0        126
It's base has a min/max of:        -128        127
The value of No_Error is:         245

raised CONSTRAINT_ERROR : constraints.adb:58 range check failed
me@acheron:~/Dropbox/programs/ada$
Run Code Online (Sandbox Code Playgroud)

源代码:

with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;

Procedure Constraints is

    type UNDER is range 0..126;
    type ON is range 0..127;
    type OVER is range 0..128;    

    Error : UNDER := 0;
    No_Error : ON := 0;

    Index : INTEGER := 0;

begin
    New_Line;
    Put("Type ON has size: ");
    Put(INTEGER(ON'SIZE));
    New_Line;
    Put("It has a min/max of: ");
    Put(INTEGER(ON'FIRST));
    Put(INTEGER(ON'LAST));
    New_Line;
    Put("It's base has a min/max of: ");
    Put(INTEGER(ON'BASE'FIRST));
    Put(INTEGER(ON'BASE'LAST));

    New_Line;
    New_Line;

    Put("Type UNDER has size: ");
    Put(INTEGER(UNDER'SIZE));
    New_Line;
    Put("It has a min/max of: ");
    Put(INTEGER(UNDER'FIRST));
    Put(INTEGER(UNDER'LAST));
    New_Line;
    Put("It's base has a min/max of: ");
    Put(INTEGER(UNDER'BASE'FIRST));
    Put(INTEGER(UNDER'BASE'LAST));

    Safe_Loop:
    loop
        No_Error := No_Error + 1;
        Index := Index + 1;
        --Put(INTEGER(No_Error));
        exit Safe_Loop when Index = 245;  
    end loop Safe_Loop;

    New_Line;
    Put("The value of No_Error is: ");
    Put(INTEGER(No_Error));

    Index := 0;

    Crash_Loop:
    loop
        Error := Error + 1;
        Index := Index + 1;
        exit Crash_Loop when Index = 245;
    end loop Crash_Loop;


end Constraints;
Run Code Online (Sandbox Code Playgroud)

rua*_*akh 3

根据文档

再次注意,-gnato默认情况下该选项处于关闭状态,因此在默认模式下不会执行溢出检查。这意味着,在默认设置下,GNAT 不会执行 Ada 参考手册中语言描述中预期的所有检查。如果您希望执行所有约束检查,如本手册中所述,则必须在gnatmakeorgcc命令上显式使用 -gnato 开关。

也就是说,该文件还声称:

基本上,规则是在默认模式(-gnato未使用)下,生成的代码确保所有整数变量保持在其声明的范围内,或者如果没有声明的范围则保持在基本范围内。这可以防止任何严重的问题,例如索引超出数组操作的范围。¶ 在默认模式下不检查的是溢出,该溢出会导致范围内但不正确的值。

在您描述的情况下这似乎是错误的,因为No_Error确实最终完全超出了其范围。因此,这似乎超出了“语言描述中不[...]预期”的范围,并进入了“编译器错误”的领域;但至少你应该能够通过添加-gnato标志来修复它。