Well, does it mean if a program compiled with $R+ it also can fail at random?
For detecting dangling pointer to freed objects: Yes.
var a: TStringList;
begin
a:= TStringList.create;
a.add('abc');
a.Destroy;
if a.count = 1 then writeln(1) else writeln('?');
end;
That code may run without error, and at random chance print 1 or ?.
var a,b: TStringList;
begin
a:= TStringList.create;
b := a;
a.add('abc');
FreeAndNil(a);
if b.count = 1 then writeln(1) else writeln('?');
end;
Same as above. FreeAndNil does not take care of the copied pointer in b. That will be dangling at this point.
$R+ is range checks? I am not sure what they activate in terms of object checking.
But fpc has various checks available:
-gh heaptrc
Afaik (needs double checking) this clears released memory, and keeps it out of circulation for a limited time => so it increases chances that the code above will crash, or that other checks will detect the error in the above code.
-CR (method checking)
wont do much on the above code. It checks that the object has the correct class if you call virtual methods.
That may or may not fail if you call a virtual method on a freed object. Basically if the memory has been altered then the class will look wrong.
Mind, this check can crash by itself. If the altered memory points to locations not owned by the app.
$OBJECTCHECKS
https://www.freepascal.org/docs-html/prog/progsu57.html#x64-630001.2.57Checks for nil. So you get an exception or run-time error rather than an access violation. But only if you nil'ed the variable.
$CHECKPOINTER
https://www.freepascal.org/docs-html/prog/progsu8.html#x15-140001.2.8That has a rather good chance to detect problems. (not 100%, but usually close to it)
Beware: this is majorly slow (IIRC)This does not check what is at the end of the pointer, but rather checks if the pointer is in the internal tables of allocated memory. So at least it should prevent the code from ever access violate.
Mind you there is a chance that even if the memory was freed, something else has allocated memory at the same location => then the check passes, even so your pointer is dangling.
And, if that something else has content that partly looks like your object then it can fool the other checks, if they are enabled too. But that is like a very very low chance.
Outside of FPC, there is
valgrind --tool=memcheck
That will detect freed pointer (including object) access reliably. It keeps track of every alloc and dealloc, and it does prevent re-use of memory (at least for a long time / need to check the docs).
Mind you, that it is majorly slow.
I heard, but do not know, that if you use the llvm backend of fpc, then there are similar checks avail, that also work (very/almost?) reliable. Not sure how much exactly....