Range checking
The last compiler option I want to discuss, Range checking, tells the compiler whether to check indexes to arrays and strings. In other words, it will check if in expression such as s[idx+1], idx+1 represents a valid index.
You can turn range checking on and off with compiler directives {$RANGECHECKS ON} and {RANGECHECKS OFF} (or {$R+} and {$R-}).
Let's take a look at an example. In the method shown here, the second for loop accesses element arr[101] without any error, although the maximum array element is arr[100]. The third for loop, however, will raise an ERangeCheck exception when accessing arr[101]:
procedure TfrmCompilerOptions.btnRangeErrorClick(Sender: TObject);
var
arr: array [1..100] of Integer;
i: Integer;
begin
for i := Low(arr) to High(arr) do
arr[i] := i;
{$R-}
for i := Low(arr) to High(arr) do
arr[i] := arr[i] + arr[i+1];
{$R+}
for i := Low(arr) to High(arr) do
arr[i] := arr[i] + arr[i+1];
end;
This kind of checking is so important that I always leave it in my code, even in the release version. Accessing a nonexistent array or string element may not seem so dangerous, but what if you are writing into that element? If this is not caught, your code just overwrites some other data with nonsense values. This leads to extremely hard to find problems! By default, range checking is turned off even in debug build and you really should turn it on in every program.
What about the "cost" of this checking? As the CompilerOptions program shows, it can be significant. In this example, turning range checking on slows down the code by a whole 50%:
In such cases, turning range checking off can speed up the program. I would still recommend that you do that just for critical parts of code, not for the whole program.
This brings us to the end of this very long, but necessary, section as understanding the
developer tools is always a good thing. Let us now—finally!—switch to something more interesting, to real programming.