Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Warum wird TObject.Free nicht gleich auf nil gesetzt (https://www.delphipraxis.net/204222-warum-wird-tobject-free-nicht-gleich-auf-nil-gesetzt.html)

Hobbycoder 7. Mai 2020 23:24

Warum wird TObject.Free nicht gleich auf nil gesetzt
 
Ich habe gerade eine ganze Zeit mit der Fehlersuche zugebracht.
Der Fehler war natürlich ganz trivial. Ich habe irgendwo ein Object mit Free freigegeben und später im Code auf NIL geprüft, was natürlich nicht funktionierte. Erst ein FreeAnNil() funktionierte dann wie erwartet. Kurzer Blick die System-Unit, und es war klar.
Delphi-Quellcode:
destructor TObject.Destroy;
begin
end;

procedure TObject.Free;
begin
// under ARC, this method isn't actually called since the compiler translates
// the call to be a mere nil assignment to the instance variable, which then calls _InstClear
{$IFNDEF AUTOREFCOUNT}
  if Self <> nil then
    Destroy;
{$ENDIF}
end;
Jetzt werden sicher einige von euch die Hände über dem Kopf zusammenschlagen.

Daher bitte auf diese Frage konzentrieren: Warum ist das so?
Wenn ich ein Object per Free freigebe ist doch im Grund klar, das ich das Object nicht mehr benötige. Warum wird es dann nicht gleich auf nil gesetzt?
Gibt es Fälle, in den sowas sinnvoll ist? Oder ist das Compilertechnisch einfach nur nicht machbar, dass sich das Object selbst auf nil setzt?

Neutral General 7. Mai 2020 23:46

AW: Warum wird TObject.Free nicht gleich auf nil gesetzt
 
Weil du genau genommen Objekte nicht auf nil setzen kannst. Du kannst Variablen die auf Objekte verweißen auf nil setzen.
Und genau darin besteht das Problem. Du kannst 10 verschiedene Variablen haben die alle auf das selbe Objekt verweisen.
Aber weder der Compiler noch sonst wer weiß wer oder was evtl. noch Referenzen auf ein Objekt hat um die entsprechenden Variablen beim Freigeben auf nil setzen zu können.
FreeAndNil ist im Grunde nichts anderes als

Delphi-Quellcode:
objVar.Free;
objVar := nil;
Aber bei FreeAndNil musst du auch explizit die Variable übergeben die du dann auf nil setzen willst.
Mal ein Beispiel:

Delphi-Quellcode:
objVar1 := TObject.Create;
objVar2 := objVar1;
objVar3 := objVar1;

FreeAndNil(objVar1);
Das Objekt hinter objVar1 wird freigegeben und objVar1 ist nil.
objVar2 und objVar3 sind aber immernoch <> nil und zeigen auf den Speicherbereich wo das Objekt vorher war.
Ein Zugriff oder sogar ein weiterer Aufruf von Free oder FreeAndNil auf objVar2 oder objVar3 führt zu einer Zugriffsverletzung.

Aber das Grundverständnisproblem was du hast ist, dass die Variable nur eine Referenz (einen Pointer) auf das eigentliche Objekt im Speicher enthält.
Es macht logisch gesehen daher gar keinen Sinn davon zu sprechen dass sich das Objekt selbst auf nil setzt.

hoika 8. Mai 2020 04:41

AW: Warum wird TObject.Free nicht gleich auf nil gesetzt
 
Hallo,
schön erklärt als ein Grund.

Der zweite Grund:
Das Nil-Setzen ist ein zusätzlicher Befehl,
der oft einfach nicht notwendig ist,
wenn das Objekt zum Beispiel in einer Methode erzeugt,
und nach der Nutzung wieder freigegeben wird.

himitsu 8. Mai 2020 08:15

AW: Warum wird TObject.Free nicht gleich auf nil gesetzt
 
Ja, jemand kam auf die geniale aublöde Idee ein DisposeOf zu erfinden, anstatt das neue "Verhalten" ins Free reinzubauen.

Echt geil, denn damit gibt es wieder einen Grund, weswegen Code nicht mehr sooooo abwärtskompatibel wird, wie man früher mal so stolz verkündet hat.
Es ist inzwischen oftmals eh unmöglich geworden ohne IFDEFs noch einen platformübergreifenden Code zu schreiben, der auch in älteren Delphis läuft, selbst wenn man nur Grundfunktionen der RTL benutzt.
Und eine Unit die mit FMX und VCL klar kommt, bzw. z.B. ein BitMap oder Canvas bemalt, aber jeder einen anderen Typ benutzt ... wie soll das gehen, wenn man in der Unit nicht prüfen kann, was es von Beidem genutzt wird.


Nja, Free ist eine "normale" Methode und das bekommt nur den Wert, aber nicht die Adresse der Variabble rein, somit kann es nichts auf NIL setzen.

hoika 8. Mai 2020 09:04

AW: Warum wird TObject.Free nicht gleich auf nil gesetzt
 
Hallo,
Zitat:

wie soll das gehen, wenn man in der Unit nicht prüfen kann, was es von Beidem genutzt wird.
IFDEF ?

*druck*

himitsu 8. Mai 2020 10:31

AW: Warum wird TObject.Free nicht gleich auf nil gesetzt
 
Ja, und auf was willst du prüfen?

Hobbycoder 8. Mai 2020 12:05

AW: Warum wird TObject.Free nicht gleich auf nil gesetzt
 
Okay, danke für eure Erklärungen. Jetzt ist mir klar, warum das nicht geht.

Also kann ich mir das so vorstellen, dass das .Free letztlich (nicht nur) für den MemoryManager da ist, um ihm mitzuteilen, dass der reservierte Speicher nicht mehr benötigt wird, und das :=nil lediglich die Zeiger des Object auf 0, -1, oder was auch immer, setzt.

Klar, dass das Object selbst nicht weiß, in welcher Variable sein Zeiger gespeichert ist, ist irgendwie logisch.
Und wenn ich so überlege, macht das durch aus Sinn, Zeiger auf nil setzen zu können ohne das Object zu zerstören.

stahli 8. Mai 2020 12:18

AW: Warum wird TObject.Free nicht gleich auf nil gesetzt
 
Zu dem Thema kannst Du Dir auch mal "automatische Referenzzählung bei Interfaces" ansehen.
Ich arbeite nahezu nur noch damit. Hat natürlich auch seine Nachteile, mit denen man dann leben muss.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:42 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz