![]() |
Objekte freigeben
Hallo zusammen,
ich bekomme bei meinem Projekt eine Fehlermeldung (EInvalidPointer) bei Beendigung des Programmes. Die Ursache liegt darin, dass Objekte mit Free freigegeben werden, die bereits an anderer Stelle freigegeben wurden. Nun meine Frage: Wie kann ich feststellen, ob ein Objekt schon freigegeben wurde? Leider wird ein Objekt bei der Freigabe offensichtlich nicht automatisch Nil gesetzt. Der Aufruf von TObject.Free ist unkritisch, wenn ein Objekt noch nicht initialisirt wurde. Wenn es aber bereits freigegeben wurde, führt der nochmalige Aufruf von Free zum Absturz. Wie kann man das verhindern? Für Hinweise und Ratschläge wäre ich dankbar! |
Re: Objekte freigeben
Delphi-Quellcode:
FreeAndNil (Object);
if Assigned (Object) then ... |
Re: Objekte freigeben
Danke für den Hinweis. Da hätte ich auch selber drauf kommen können. Habs auch gleich ausprobiert. Es hilft aber nicht in dem folgenden Fall.
Ich habe eine von TWorldBox und damit von TComponent abgeleitete Klasse.
Delphi-Quellcode:
Ein oder mehrere Komponenten vom Typ TMyBox erzeuge ich im Programm dynamisch aus einem übergeordneten Objekt TArea heraus. Dieses Objekt weist MyBox auch verschienen Parametersätze zu (ParameterA, ParameterB, ParameterC). Da ich nicht weiss, welcher Parametersatz am Ende in MyBox verlinkt ist, gebe ich im Destructor von TArea alle drei frei.
TMyBox = class(TWorldBox)
public { Public-Deklarationen } Parameter : TParmeter; destructor Destroy; override; end; destructor TMyBox.Destroy; begin FreeAndNil(Parameter); inherited Destroy; end;
Delphi-Quellcode:
Beim Programmende gibt es aber Probleme. Die Komponente MyBox wird von Delphi schon freigegeben bevor der Destructor von TCalcArea aufgerufen wird. Und Delphi scheint nicht über FreeAndNil freizugeben (Warum eigentlich nicht). Zusätzlich gibt es Probleme beim Freigeben des Parametersatzes der schon über MyBox freigegeben wurde.
TArea = class(TObject)
MyBox : TMyBox; ParameterA, ParameterB, ParamterC: TParameter; constructor Create; destructor Destroy; override; end; constructor TArea.Create; begin MyBox := TMyBox.Create(MainForm); ParameterA := MyBox.Parameter; ParameterB := TParameter.Create; ParameterC := TParameter.Create; end; destructor TCalcArea.Destroy; begin FreeAndNil(ParmeterA); FreeAndNil(ParmeterB); FreeAndNil(ParmeterC); FreeAndNil(MyBox); inherited Destroy; end; Was kann man daran ändern? |
Re: Objekte freigeben
Dort wo du etwas freigibt, die Variable auf NIL setzen
Delphi-Quellcode:
das letzte FreeAndNil wird nicht ausgeführt, da Parameter1 schon vorher freigegeben und auch als frei markiert (NIL) wurde.
ParameterA := MyBox.Parameter;
FreeAndNil(ParmeterA); If Assign(ParmeterA) Then FreeAndNil(ParmeterA); |
Re: Objekte freigeben
Erst mal danke, dass ihr Euch da hineindenkt!
Das mit dem FreeAndNil habe ich schon verstanden. (Brauch man danach die Abfrage mit Assigned eigentlich noch oder testet Free bzw. FreeAndNil nicht selbt auch Nil?) Das Problem in meinem Fall ist aber wahrscheinlich, dass beim Beenden des Programms zuerst die Komponenete MyBox von Delphi freigegeben wird und danach eben nicht auf Nil gesetzt wird. Genauso ist der innerhalb von MyBox verlinkte Paramter nicht Nil. |
Re: Objekte freigeben
FreeAndNil testet eigentlich nichts (glaub ich)
FreeAndNil macht auch nichts anderes, als
Delphi-Quellcode:
procedure FreeAndNil(Obj)
begin Temp := Obj; Obj := nil; Temp.Free; end; |
Re: Objekte freigeben
Schon - aber Free testet ungefähr so:
Delphi-Quellcode:
;)
procedure Free
begin if Self <> nil then Destroy; end; |
Re: Objekte freigeben
Zitat:
|
Re: Objekte freigeben
Hi Luckie,
das klingt einleuchtend und könnte mein Problem beheben. Danke für den Hinweis. |
Re: Objekte freigeben
Zitat:
Delphi-Quellcode:
wirft eine 'Externe Exception C00001D' (in D6, und etwas ähnliches in D2009).
procedure TForm1.FormCreate(Sender: TObject);
var X: TObject; // aus SysUtils.pas procedure FreeAndNil(var Obj); var Temp: TObject; begin Temp := TObject(Obj); Pointer(Obj) := nil; Temp.Free; end; begin FreeAndNil(X) end; Warnungen oder Hinweise wegen der nicht initialisierten Variable X gibt es keine - da muss man halt aufpassen :) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz