Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cause of Range Check Error (Delphi)

Here's a condensed version of some code that causes both a Range check error and an overflow error, should I turn on those compiler check directives. I understand why this would cause an overflow, on the multiplication of C1, it seems likely it might exceed the data-type's max valude. But why would this also trigger a Range-check error? Delphi's documentation and other posts on stack overflow make it sound like range-check errors are usually for array accesses that are out of bounds. But I'm not accessing an array on the line it's saying is causing the range-check error. Perhaps its on the assignment to param1? But why would that be a range-check and not an overflow error, if so?

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;

If it's relevant, when it breaks on that line in the debugger, all the values look as expected, except param1, which shows "Undeclared identifier: 'param1'" when I ask Delphi to evaluate it.

like image 663
Jessica Brown Avatar asked Jul 25 '12 20:07

Jessica Brown


People also ask

What does Range Check error mean in Delphi?

The $RangeChecks directive tells the compiler to generate code that checks array operations to ensure that the array index is within the array bounds. If an index is out of bounds, Delphi reports runtime error 4 ( ERangeError ).

What does Range check error mean?

The RangeError object indicates an error when a value is not in the set or range of allowed values.


1 Answers

The documents about range-checking states:

The $R directive enables or disables the generation of range-checking code. In the {$R+} state, all array and string-indexing expressions are verified as being within the defined bounds, and all assignments to scalar and subrange variables are checked to be within range. If a range check fails, an ERangeError exception is raised (or the program is terminated if exception handling is not enabled).

So the reason here is the assignment to a scalar value, which is handed a value that has passed the upper range.

See also docwiki Simple Types about range-checking errors on simple types and subrange types.

Example:

{$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;

A summary test of all combinations of $R and $Q for all platform-independent integer types:

            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=Range error; O=Overflow error; x=Nothing

And the test was(pseudo-code) with XE2 in 32-bit mode:

number := High(TNumber);
number := number + 1;
like image 131
LU RD Avatar answered Sep 20 '22 03:09

LU RD