Man sollte sowieso überlegen ob man wirklich FreeAndNil verwenden will, denn grundsätzlich versteckt es Fehler:
Doppeltes free ist ganz klar ein Fehler, und normalerweise eine Indikation das irgendwo im Code falsche Annahmen über die Lebenszeit des Objekts getroffen wurden (z.b. wenn's keinen eindeutigen owner gibt).
Und wenn man einen Fehler im Code hat will man das es kracht, zum einen damit das Programm nicht im Fehlerstate weiter läuft (und potentiell noch mehr Schaden anrichtet) und damit man einen stack trace und debug Infos bekommt was wo schief gegangen ist.
Der Code oben crasht mit einem Fehler, das ist gut. Ersetzt man den Aufruf zu Free jetzt durch FreeAndNil crasht es nicht mehr, der Fehler bleibt unentdeckt und es geht womöglich noch mehr kaputt:
Code: Alles auswählen
sl:=TStringList.Create;
FreeAndNil(sl);
FreeAndNil(sl);
Mal ganz davon abgesehen das in den allermeisten Fälle FreeAndNil eh nix bringt da die meisten Fälle von use after free die FreeAndNil verhindern soll, kommen dadurch zustande das man mehrere Referenzen auf die selbe Instanz hat:
Code: Alles auswählen
sl:=TStringList.Create;
sl2:=sl;
FreeAndNil(sl);
if assigned(sl2) then WriteLn(sl2.text);
Hier macht FreeAndNil nix.
Also zusammengefasst: FreeAndNil verhindert use-after-free in den meisten nicht trivialen Programmen sowieso nicht, und in den Fällen in denen es das tun kann, kann es Fehler sogar verstecken.
Wenn man Speichersicherheit sicherstellen will gibt es bessere Methoden dafür, z.b. Nutzung eines strikten ownership Modells (wie das component system), Verwendung von managed Typen wie Interfaces, oder Records, etc.
Und natürlich eins: testen, testen, testen...
Insbesondere mit Heaptrc (Tipp: KeepReleased) oder Valgrind