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.
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 ).
The RangeError object indicates an error when a value is not in the set or range of allowed values.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With