Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Objekte freigeben (https://www.delphipraxis.net/129783-objekte-freigeben.html)

SteffenSchm 25. Feb 2009 13:47


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!

nuclearping 25. Feb 2009 13:49

Re: Objekte freigeben
 
Delphi-Quellcode:
FreeAndNil (Object);

if Assigned (Object) then
  ...

SteffenSchm 25. Feb 2009 14:27

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:
TMyBox = class(TWorldBox)
  public
    { Public-Deklarationen }
    Parameter      : TParmeter;
    destructor Destroy; override;
   end;

destructor TMyBox.Destroy;
begin
  FreeAndNil(Parameter);
  inherited Destroy;
end;
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.

Delphi-Quellcode:
  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;
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.

Was kann man daran ändern?

himitsu 25. Feb 2009 14:39

Re: Objekte freigeben
 
Dort wo du etwas freigibt, die Variable auf NIL setzen

Delphi-Quellcode:
ParameterA := MyBox.Parameter;

FreeAndNil(ParmeterA);

If Assign(ParmeterA) Then FreeAndNil(ParmeterA);
das letzte FreeAndNil wird nicht ausgeführt, da Parameter1 schon vorher freigegeben und auch als frei markiert (NIL) wurde.

SteffenSchm 25. Feb 2009 14:53

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.

himitsu 25. Feb 2009 15:06

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;

jfheins 25. Feb 2009 15:08

Re: Objekte freigeben
 
Schon - aber Free testet ungefähr so:

Delphi-Quellcode:
procedure Free
begin
if Self <> nil then
  Destroy;
end;
;)

Luckie 25. Feb 2009 16:46

Re: Objekte freigeben
 
Zitat:

Zitat von SteffenSchm
Delphi-Quellcode:
MyBox         := TMyBox.Create(MainForm);

FreeAndNil(MyBox);

Du hast also Owner deine Form angegeben. Somit übernimmt auch deine Form das Zerstören des Objektes. Du versuchst es aber selber noch mal frei zugeben. Entweder gibst du beim Erzeugen keinen Owner an und kümmerst dich selber ums Freigeben oder aber du gibst einen Owner an und überlässt ihm das Freigeben.

SteffenSchm 25. Feb 2009 16:49

Re: Objekte freigeben
 
Hi Luckie,

das klingt einleuchtend und könnte mein Problem beheben. Danke für den Hinweis.

mjustin 25. Feb 2009 17:43

Re: Objekte freigeben
 
Zitat:

Zitat von jfheins
Schon - aber Free testet ungefähr so:

Delphi-Quellcode:
procedure Free
begin
if Self <> nil then
  Destroy;
end;
;)

Hilft auch nicht immer:

Delphi-Quellcode:
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;
wirft eine 'Externe Exception C00001D' (in D6, und etwas ähnliches in D2009).

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 03:39 Uhr.
Seite 1 von 3  1 23      

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