$rangeChecks

From Lazarus wiki
Jump to navigationJump to search

The FPC’s local compiler directive {$rangeChecks} enables or disable range checks of ordinal data type expressions, the default being {$rangeChecks off}. The short form {$R+} and {$R-} is recognized too.

range checks

A range check ensures a value is within the domain of the destination operand. As soon as an operand needs to be “squeezed” into a smaller range, the expression or statement is eligible to a range check.

behavior

If a range check fails, the runtime error 201 “Range check error” is generated. Thus the code sample

	{$rangeChecks on}
	x := y;

is semantically equivalent to

	{$rangeChecks off}
	x := y;
	if (x < low(x)) or (x > high(x)) then
	begin
		runError(201);
	end;

(The reported memory address at which the error occurred will differ and the compiler may produce optimized code.)

eligibility

Range checks can be performed

  • in assignments (:=), and more specifically
    • when passing actual parameters, or
    • indicating array indices, but also
  • when doing typecasts.

For assignments involving constant expressions a range check is performed already at compile-time, but is either a warning or error depending on the current setting.

placement

The FPC allows enabling and disabling range checks on a per-statement basis, while Delphi allows changing the setting only a per-routine level.

caveats

  • It is important to remember that in Pascal arithmetic expressions are always evaluated on a computer’s “native” (signed) integer data type. If the destination operand of an arithmetic expression is, for instance a ALUSInt, this will never trigger a runtime error.
  • If range checks are meant to be performed when passing parameters, range checks must be enabled at the call site.

application

Range checks can incur a significant performance penalty. Therefore, the FPC disables range checks by default. However, at least during development and prior releases of software, range checks should be enabled to find “obvious” programming mistakes. As a consequence of this practice, if a code fragment is meant to exceed the permissible range, it should be documented like this:

	{$push}
		{$rangeChecks off}
		x := y;
	{$pop}

Use {$ifOpt} if code needs to be different on the current range-check-setting:

	{$ifOpt R-} // or R+
		
	{$endIf}