11

如果我打开那些编译器检查指令,这是一些导致范围检查错误和溢出错误的代码的精简版本。我理解为什么这会导致溢出,在 C1 的乘法中,它似乎可能超过数据类型的最大值。但是为什么这也会触发范围检查错误呢?Delphi 的文档和其他关于堆栈溢出的帖子听起来像是范围检查错误通常是针对超出范围的数组访问。但我没有访问它所说的导致范围检查错误的行上的数组。也许它分配给param1?但是,如果是这样,那为什么会是范围检查而不是溢出错误呢?

const
  C1 = 44001;
  C2 = 17999;

function fxnName(..other params...; param1: Word): String;
var
  someByte: byte;
begin
  // some code
  // by now we're in a loop. the following line is where it breaks to in the debugger: 
  param1 := (someByte + param1) * C1 + C2;
  // more code
end;

如果它是相关的,当它在调试器中的该行中断时,所有值看起来都符合预期,除了 param1,当我要求 Delphi 评估它时,它显示“未声明的标识符:'param1'”。

4

1 回答 1

20

有关范围检查的文档指出:

$R 指令启用或禁用范围检查代码的生成。在 {$R+} 状态下,所有数组和字符串索引表达式都被验证是否在定义的范围内,并且所有对标量和子范围变量的赋值都被检查是否在范围内。如果范围检查失败,则会引发 ERangeError 异常(或者如果未启用异常处理,程序将终止)。

所以这里的原因是分配给一个标量值,它被传递一个已经超过上限的值。

另请参阅docwiki Simple Types关于简单类型和子范围类型的范围检查错误。

例子:

{$R+} // Range check on
var
  w1,w2 : word;
begin
  w1 := High(word);
  w1 := w1 + 10; // causes range-check error on assignment to w1 (upper range passed)
  w2 := 0;
  w2 := w2 - 10; // causes range-check error on assignment to w2 (lower range passed)
end;

对所有平台无关整数类型的 $R 和 $Q 的所有组合的总结测试:

            R+Q+  R+Q-  R-Q+
 ShortInt    R     R     x
 SmallInt    R     R     x
 Integer     O     x     O
 LongInt     O     x     O
 Int64       O     x     O
 Byte        R     R     x
 Word        R     R     x
 LongWord    O     x     O
 Cardinal    O     x     O
 UInt64      O     x     O

R=范围误差;O=溢出错误;x=无

并且测试是(伪代码)在 32 位模式下使用 XE2:

number := High(TNumber);
number := number + 1;
于 2012-07-25T21:22:59.797 回答