我一直在看这个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;
答案 0 :(得分:3)
再次注意,默认情况下
-gnato
处于关闭状态,因此在默认模式下不会执行溢出检查。这意味着开箱即用,使用默认设置,GNAT不会执行Ada参考手册中语言描述所需的所有检查。如果要执行所有约束检查(如本手册中所述),则必须在gnatmake
或gcc
命令上明确使用-gnato开关。
那就是说,文件还声称:
基本上规则是在默认模式(
-gnato
未使用)中,生成的代码确保所有整数变量都保持在其声明的范围内,或者如果没有声明的范围则保持在基本范围内。这可以防止任何严重的问题,例如数组操作的索引超出范围。 ¶默认模式下未检查的是溢出,导致范围内但值不正确。
在你描述的情况下似乎是错误的,因为No_Error
确实最终完全超出了它的范围。所以这似乎超出了“不期望从语言描述中”到“编译器bug”的范围;但至少你应该能够通过添加-gnato
标志来修复它。