Reputation: 6607
A customer has reported a Range check error
on a machine embedded in a factory running an older Delphi 7 application. We have not (yet) been able to reproduce the error. They sent us a photo:
The software can operate correctly for days on end, and we currently only have vague clues as to how this might be generated or reliably reproduced. My understanding is that this error occurs in two general scenarios:
(1) An array or string has been accessed outside its bounds
(2) The variable is assigned a value out-of-range for its type
An example of (1) is accessing array[50] if there are only 40 elements. An example of (2) is assigning the value "300" to an an unsigned BYTE.
This comes from SO question 1 and SO question 2. I've got lots of careful checking to do to try and identify the offending lines!
My question is how this error is generated in the first place. Both the above-mentioned questions refer to the {$R+}
compiler directive. In Project Options > Compiler > Runtime errors, Range checking
is off, and nowhere in the code is {$R+}
(nor {$R-}
) used. How does this error occur? Shouldn't the application crash or generate a different exception?
Upvotes: 0
Views: 3294
Reputation: 14832
I'll answer the question:
Can a Range check error be generated without being specifically enabled?
However, the problem you're experiencing at your client's site will need further investigation for you to resolve it. Typically this kind of thing requires a combination of:
Yes, range check error can be generated without being specifically enabled.
raise ERangeError.Create(...);
. If called, this will raise the error regardless of the state of the range-check setting.Note code can if so written, also honour the setting as follows:
{$IFOPT R+}
raise ERangeError.Create(...);
{$ENDIF}
But the point is that as soon as raise <SomeClass>.Create(...)
is called, an exception will be raised. If you search the Delphi source code, you'll find a few places where ERangeError
is raised. Loki's answer provides an example.
{$R}
setting is not global. If you compile a project with this setting turn off, but link in DCUs which were compiled with the option turned on: then the setting will still be on for those DCUs.Furthermore, the setting can be locally changed for specific sections of code. E.g.
{$IFOPT R-} {$R+} {$DEFINE TOGGLE_ROFF} {$ENDIF}
{ Ensure range-checking is on, but turn off again if it was already off.}
procedure MustUseRangeChecking(...);
begin
...
end;
{$IFDEF TOGGLE_ROFF} {$R-} {$ENDIF}
NOTE: You can use {$IFOPT}
in your own code to check the state of the range-checking directive.
Upvotes: 4
Reputation: 13367
yes it's can be raise without having Range check error specifically enabled
exemple just look the TStream.SetSize function :
procedure TStream.SetSize(const NewSize: Int64);
begin
if (NewSize < Low(Integer)) or (NewSize > High(Integer)) then
raise ERangeError.CreateRes(@SRangeError);
SetSize(LongInt(NewSize));
end;
so it's will raise the exception with or without Range check error enabled. you have in delphi several function like this.
Upvotes: 4