Ada CONSTRAINT_ERROR在“应该”时没有被提升

时间:2012-10-10 02:23:28

标签: exception ada gnat

我一直在看这个Ada 95 tutorial。我读到可以定义一个范围不同于标准范围的类型,如果程序试图超出这个范围,它将引发错误。在处理我自己的程序时,我注意到如果定义中范围的末尾落在其基础类型的边界上,那么程序在分配超出该范围的值时将不会引发CONSTRAINT_ERROR。相反,它会愉快地继续前进,然后环绕。我写了一个程序来明确地表明这一点。

是否有人知道解释此行为的Ada规则?

-Kirk

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

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;

1 个答案:

答案 0 :(得分:3)

根据the documentation

  

再次注意,默认情况下-gnato处于关闭状态,因此在默认模式下不会执行溢出检查。这意味着开箱即用,使用默认设置,GNAT不会执行Ada参考手册中语言描述所需的所有检查。如果要执行所有约束检查(如本手册中所述),则必须在gnatmakegcc命令上明确使用-gnato开关。

那就是说,文件还声称:

  

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

在你描述的情况下似乎是错误的,因为No_Error确实最终完全超出了它的范围。所以这似乎超出了“不期望从语言描述中”到“编译器bug”的范围;但至少你应该能够通过添加-gnato标志来修复它。