5

我一直在看这个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$

源代码:

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

1 回答 1

3

根据文档

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

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

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

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

于 2012-10-10T03:01:28.880 回答