Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Probleme mit TObject.Free (https://www.delphipraxis.net/54677-probleme-mit-tobject-free.html)

LoRd-MuldeR 9. Okt 2005 16:38


Probleme mit TObject.Free
 
Hallo zusammen erstmal!
Ich hätte da mal en kleines Problem und hoffe hier kann mir jemand weiterhelfen :-D

Ich habe ein eigenes Objekt nach folgendem Schema definiert:

Delphi-Quellcode:
type
  TMyObj = class(TObject)
  public
    constructor Create(Param:String);
    destructor Destroy; override;
  private
    procedure DoSomething;
  end;
das Objekt lässt sich mit Create herstellen und mit Free zerstören

Delphi-Quellcode:
procedure Foobar;
var
  MyObj: TMyObj;
begin
  try
    MyObj := TMyObj.Create('Oi!');

    MyObj.DoSomething;
    [...]
  finally
    MyObj.Free;
  end;
end;
So, nun das Problem:

Ich habe festgestellt, dass ein erneuter Aufruf von .Free - also wenn das Object bereits mit .Free zerstört wurde - zu einem Exception Error führt (Memory Access Violation). So weit ich es verstanden hab, sollte das Objekt doch nach dem ersten .Free aufruf zerstört und somit wieder nil sein. Ein zweiter Aufruf von .Free sollte dies erkennen und keinen Fehler verursachen. Das is doch der Grund, warrum ich .Free anstatt .Destory aufrufe, oder? Iregndwie schein meint Objekt aber nach dem Zerstören durch .Free nich nil zu werden. Ergo: Der Speicher wurde nich korrekt freigegeben.

Wo steckt bloß der Fehler ???
Oder hab ich da was falsch verstanden?

Keldorn 9. Okt 2005 16:43

Re: Problem with TObject.Free
 
Hallo
.free setzt das object nicht automatisch auf Nil, das mußt du selbst tun. Dafür gibt es
Delphi-Quellcode:
FreeAndNil(myobject);
Mfg Frank

LoRd-MuldeR 9. Okt 2005 16:46

Re: Probleme mit TObject.Free
 
Cool, danke für die superschnelle Antwort :-D

Warrum steht sowas nich in der Anleitung ???

Sollte ich dann also immer FreeAndNil(MyObj) anstatt MyObj.Free benutzen, damit der Speicher korrekt freigegeben wird?

Hansa 9. Okt 2005 16:47

Re: Probleme mit TObject.Free
 
Bin gerade auch mit so was beschäftigt. Versuche das hier mal :

Delphi-Quellcode:
Abject.Destroy;
Aject := nil;
Allerdings wäre interessant zu wissen, wo das Objekt herkommt / rzeugt wird.

LoRd-MuldeR 9. Okt 2005 16:50

Re: Probleme mit TObject.Free
 
@Hansa:

Du solltest .Free anstatt .Destroy aufrufen, so viel is sicher.
Aber scheint so, als ob du das Objekt hinterher noch manuell auf nil setzten musst!
Ich denke am besten isses dieses FreeAndNil(TObject) zu benutzen, wie es Keldorn vorgeschlagen hat...

LoRd-MuldeR 9. Okt 2005 16:59

Re: Probleme mit TObject.Free
 
Hab grad en Beispiel gefunden. Schaut mal hier:
http://www.delphibasics.co.uk/RTL.asp?Name=FreeAndNil

woki 9. Okt 2005 17:33

Re: Probleme mit TObject.Free
 
Zur Erklärung:

Myobj.free zerstört das Objekt und gibt den Speicherplatz frei.
MyObj := nil setzt die Referenz auf das Objekt zurück, denn Myobj ist nicht das Objekt sondern ein Zeiger darauf.

LoRd-MuldeR 9. Okt 2005 18:03

Re: Probleme mit TObject.Free
 
Okay, soweit verstanden.

Aber wozu is eine Referenz auf ein zerstörtes Objekt gut, so wie es .Free hinerlässt?
Das führt doch höchstens zu Exceptions, z.B. wenn man nochmal .Free benutzt!

Also werde ich dann zukünftig FreeAndNil(TObject) anstatt TObject.Free benutzen, um Probleme zu vermeiden.

marabu 9. Okt 2005 18:08

Re: Probleme mit TObject.Free
 
Hallo Lord,

das dangling pointer problem entsteht erst durch globale Zeigervariablen. Je mehr solche globalen Variablen du eliminierst, desto bedeutungsloser werden deine Maßnahmen zur Eindämmung möglicher Programmschäden - am Ende kannst du wieder rein objekt-orientiert mit der Methode Free() arbeiten.

Grüße vom marabu

damned dropped characters

LoRd-MuldeR 9. Okt 2005 18:45

Re: Probleme mit TObject.Free
 
Das Problem lässt sich aber in meinem Fall nich so ohne weiteres Umgehen, da ich teilweise nich vorhersagen kann, ob das Objekt bereits zerstört wurde. Natürlich gäbe es da auch wege, das Problem anders zu lösen. Aber FreeAndNil(Obj) scheint doch ne ganz elegante Lösung zu sein!

Keldorn 9. Okt 2005 18:51

Re: Probleme mit TObject.Free
 
Hallo

wieso weißt du nicht, ob das Object nicht schon freigegeben wurde? Wenn du so vorgehst, wie in deinem Bsp, kann doch gar nix passieren. Ich verwende eigentlich nie FreeAndNil und hab trotzdem keine Probleme mit der doppelten Freigabe.

Mfg Frank

LoRd-MuldeR 9. Okt 2005 18:57

Re: Probleme mit TObject.Free
 
So schön einfach wie im Beispiel sieht die Sache leider nich aus :?

Mein Problem war ja auch hauptsächlich, dass ich dachte mein Objekt müsste wieder nil sein, nachdem ich .Free benutz hab. Weil das ja nich so war, hab befürchtet, ich hätte was vergessen bzw. falsch gemacht. Vorallem was den destructor angeht. Aber wenn das normal is, dass .Free einen "dangling pointer" hinterlässt, is ja alles soweit okay. Muss man ja nur wissen, dann kann man damit umgehen. In der Anleitung is das leider mit keinem Wort erwähnt. Da steht ja extra man soll .Free statt .Destroy nehmen, damit man nich darauf achten muss, ob das Objekt bereits nil is. Vondaher wäre es schlüssig gewesen, wenn das Objekt nach .Free wieder nil wäre. Is halt nich so...

Also noch ma danke für die Hilfe :hi:

Khabarakh 9. Okt 2005 19:18

Re: Probleme mit TObject.Free
 
Zitat:

Zitat von LoRd-MuldeR
Aber wenn das normal is, dass .Free einen "dangling pointer" hinterlässt, is ja alles soweit okay.

Wenn es anders wäre, wäre Free abnormal :wink: . Denn Free ist ja eine Methode von TObject und kann (ohne zusätzlichen Parameter o.Ä.) damit nicht auf die Referenz der Instanz zugreifen und sie nil setzen. Das wäre nur durch Compiler-Magic möglich.

teebee 9. Okt 2005 20:40

Re: Probleme mit TObject.Free
 
Edit: Vergiss es, war Quatsch...

Gruß, teebee

Hansa 9. Okt 2005 20:47

Re: Probleme mit TObject.Free
 
Mein Posting hat wohl keiner gelesen. 8) Der Tip kommt von Borland selber ! Destroy und auf NIL setzen ist die Methode, die wasserdicht sein soll. Allerdings habe ich gemerkt, daß egal wie, das alles keine grossen Auswirkungen hat.

teebee 9. Okt 2005 20:51

Re: Probleme mit TObject.Free
 
Wieso Destroy+Nil "wasserdichter" sein soll als Free+Nil oder FreeAndNil ist mit nicht klar. Free ruft auch nur Destroy auf, prüft vorher aber noch auf self<>nil und verhindert so eine AV, die man sonst bekäme, wenn self schon nil ist.

Gruß, teebee

marabu 9. Okt 2005 21:28

Re: Probleme mit TObject.Free
 
Hallo Hansa,

Zitat:

Der Tip kommt von Borland selber ! Destroy und auf NIL setzen ist die Methode, die wasserdicht sein soll.
hast du einen Beleg für deine Behauptung? Würde mich sehr interessieren...

marabu

LoRd-MuldeR 9. Okt 2005 23:15

Re: Probleme mit TObject.Free
 
@Hansa:
Also, dass man TObject.Free und eben *nicht* TObject.Destroy aufrufen soll, steht doch explizit in der offiziellen Delphi Hilfe-Datei. Macht ja auch Sinn, weil - wie schon oft gesagt - TObject.Free auch nichts anderes tut als TObject.Destroy aufzurufen. Der einzige Unterschied: TObject.Free verhindert, dass ein TObject = nil einen AV Error verursacht. Von daher is TObject.Free die sichere Methode!

Aber TObject wird dabei niemals nil, weder bei TObject.Free noch bei TObject.Destroy. Ob man das "zerstörte" TObject nun als "dangling pointer" lässt oder manuell auf nil zurücksetzt, is ja nur dann interessant, wenn man zu einem späteren Zeitpunkt nochmal auf den Pointer zugreift. Also z.B. wenn man noch mal Object.Free ausführt, ohne vorhersagen zu können, ob das Objekt bereits "zerstört" wurde. Ansonsten is das grad egal...

Ob man nun FreeAndNil(Object) oder Object.Free plus Object=nil benutzt kommt auf's gleiche raus. Aber FreeAndNil() is wohl die elegantere Lösung...

Zitat:

Zitat von Delphi Basics
Example code : Free and nil an object, and then try to do this again

Delphi-Quellcode:
var
  myList : TList;

begin
  // Create the list object
  myList := TList.Create;

  // And now free and nil this object
  FreeAndNil(myList);

  // We can safely do this twice - it ignores nil objects
  FreeAndNil(myList);
end;
No exception occurs - the second FreeAndNil does nothing.


Grishnak 9. Okt 2005 23:43

Re: Probleme mit TObject.Free
 
@Hansa: es ist mir völlig neu, dass man .Destroy statt .Free benutzen soll!

LoRd-MuldeR 9. Okt 2005 23:49

Re: Probleme mit TObject.Free
 
Delphi-Quellcode:
unit System

[...]

procedure TObject.Free;
begin
  if Self <> nil then
    Destroy;
end;
:roll:

Grishnak 10. Okt 2005 23:40

Re: Probleme mit TObject.Free
 
@lord-mulder: Dass '.Free' nichts anderes macht, als auf 'nil' zu testen und dann das Objekt per '.Destroy' zerstört, war mir auch klar! :mrgreen:


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:40 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