Thema: Delphi Frage zu FreeAndNil

Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#21

Re: Frage zu FreeAndNil

  Alt 27. Feb 2010, 14:06
Zitat:
Warum soll eine Referenz auf ein Objektfeld *in einem Destruktor* auf nil gesetzt werden?
Du beantwortest also diese Frage mit "kommt nicht vor", und das ist der Denkfehler der ganzen Diskussion.

Natürlich kann sowas vorkommen bei nicht statischen Objektvariablen. Denke dir eine hiearische Struktur aus Objekten. Jedes Objekt hat ein Feld Parent und verweist auf das übergeordnete Objekt. das Übergeordnete Objekt = parent wiederum hat mehrere Objektfelder auf andere untergeordnete Objekte wie zb. Left und Right. So sieht die Struktur eines AVL/RB Baumes aus. UU. kann also folgender Zugriff nötig werden -> Self.Parent.Left. Left vom Parent kann aber in diesem Baum durchaus nil sein. Ergo wird in diesem Design vor dem Zugriff auf .Left mit Assigned(Self.Parent.Left) abgefragt. In Parent.Free wird Parent.Left und Parent.Right mit FreeAndNil() freigegeben. Das erfolgt sequentiell im Destruktor, also

Delphi-Quellcode:
begin
  FreeAndNil(Left);
  FreeAndNil(Right);
end;
Wenn nun im Destruktor von .Right selber über Parent.Left auf Left zugegriffen werden soll dann ist dies mit Assigned(Parent.Left) abgesichert. Wird im Parent nun nicht .Left auf NIL gesetzt ist das ein Designfehler.

Zusätzlich denken wir uns den Fall das die Objekte selber mit Windows Botschaften arbeiten. Ab diesem Moment wird es ein asynchrones Design da selbst bei Destruktor eines dieser Child Objekte noch Windows Botschaften reinkommen können. Innerhalb dieser Botschaften, die nicht vorhersehbar sind aus Sicht des Entwicklers dieser Struktur, wird nun über Parent.Lef/.Right zugriffen. Natürlich wieder mit Assigned() geschützt. Wird aber die Objektreferenz auf .Left/.Right nciht sauber aufgeräumt dann ist das ein Designfehler.

Man benutzt also den Status "nil" einer Objektreferenz als zusätzlichen Status, so ähnlich wie es in Datenbank den Wert NULL eines Feldes geben kann. Um darauf sauber reagieren zu können muß man FreeAndNil() und Assigned() benutzen, auch auf Grund des oben genannten "Kaskaden" Effektes.

Fazit: es ist eher umgekehrt. Wird nicht FreeAndNil() benutzt um diese Referenzen freizugeben dann ist das ein Designfehler. Besonders im Destruktor des Parents ist das dann wichtig.

Gruß Hagen

PS: übrigens behaupte ich das du keine andere konzeptionelle Lösung für obiges Problem finden wirst. Es existiert also kein anderes Design das das so kann und ergo ist obiges Szenario in keinem Fall ein Designfehler.

PPS: ich stelle also die Gegenthese auf: FreeAndNil() im Destruktor nicht zu benutzen kann uU. ein Designfehler sein, aber es in jedem Fall zu benutzen ist es mit Sicherheit nicht.
  Mit Zitat antworten Zitat