Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Interfacelisten: Objekt wird bei remove freigegeben (https://www.delphipraxis.net/138568-interfacelisten-objekt-wird-bei-remove-freigegeben.html)

alzaimar 12. Aug 2009 17:05


Interfacelisten: Objekt wird bei remove freigegeben
 
Folgender Code:
Delphi-Quellcode:
Type
  TTest = Class (TInterfacedObject, IInterface)
  End;

procedure TForm1.Button1Click(Sender: TObject);
Var
  l : TInterfaceList;
  x : TTest;

begin
  l := TInterfaceList.Create;
  x := TTest.Create;
  l.Add(x);
  L.Remove(x);
  x.free; // <<--- Peng. X ist schon freigeben. Wieso?
  l.free;
end;
Kann mir jemand erklären, was ich falsch mache bzw. wo mein Denkfehler liegt?
Ich müsste doch jedes Objekt selbst wieder freigeben, was ich per Create erzeuge, oder nicht?

himitsu 12. Aug 2009 17:09

Re: Interfacelisten: Objekt wird bei remove freigegeben
 
sowas passiert halt, wenn man Interfaces und Objekte mischt :warn:

also Objekt hat es einen Instanzzähler von 0, bei übergabe an die Interface-Variable/-Liste wird dieser auf 1 erhöht
und beim löschen/remove wieder auf 0 erniedrigt und demnach freigegeben.

Apollonius 12. Aug 2009 17:10

Re: Interfacelisten: Objekt wird bei remove freigegeben
 
Die TInterfaceList ist eine Liste von Interfaces (soweit bist du wahrscheinlich schon gekommen :mrgreen: ).
Beim .Add holt sie sich eine Referenz auf das übergebene Interface -> AddRef, Referenzzähler 1.
Beim .Remove verliert sie die Reference -> Release, Referenzzähler 0, Freigabe des Objekts.
Wie sonst auch gilt also auch hier die Regel: Interfaces und Klassen sind nur mit viel Umsicht zu vermischen. Und bei Interfaces gilt eben nicht, dass du alles mit Free freigeben musst, was du mit Create angefordert hast.

Bernhard Geyer 12. Aug 2009 17:11

Re: Interfacelisten: Objekt wird bei remove freigegeben
 
Solche Fehler von einem alten Hasen :mrgreen:

siehe auch diese Diskussion

alzaimar 13. Aug 2009 09:10

Re: Interfacelisten: Objekt wird bei remove freigegeben
 
Zitat:

Zitat von Bernhard Geyer
Solche Fehler von einem alten Hasen :mrgreen:

Ich wollte mir schon einen Alter Ego anlegen, weil mir das etwas peinlich ist :tongue: , aber es ging mir in erster Linie um das Programmdesign (Create->Process->Destroy)

Mir war das mit dem Referenzzähler auch klar, ich habe nämlich entdeckt, das ich mit meinem RAD auch debuggen kann. :thumb:

Die Frage ist nur, wieso ist das so implementiert? In meinen Augen ist das eine ziemliche Einschränkung der Sprache "Delphi", aber damit muss ich halt leben.

himitsu 13. Aug 2009 09:22

Re: Interfacelisten: Objekt wird bei remove freigegeben
 
Das ist schon OK und auch vollkommen richtig so. :angel:

Wenn du es mischen willst, dann bleiben dir grundsätzlich 2 Möglichkeiten_

- entweder du schaltest die Referenzzählung ab
und gibst selber frei, mußt dann aber auch aufpassen, daß beim Freigeben das Objetzt nicht doch nocht irgendwo benötigt wird, weil z.B. irgendwo eine Intervace-Variable noch nicht freigegeben wurde

- oder du sagst, daß du gern eine Instanz für deine Objektbehandlung hättest
Delphi-Quellcode:
l := TInterfaceList.Create;
x := TTest.Create;
x._AddRef;
l.Add(x);
L.Remove(x);
x._Release;
l.Free;

Stevie 13. Aug 2009 09:33

Re: Interfacelisten: Objekt wird bei remove freigegeben
 
Grundregel, wenn du nicht die Referenzzählung außer Kraft setzen oder anderweitig "austricksen" willst: niemals mit Objektreferenzen sondern immer mit Interfacereferenzen arbeiten, wenn dir die Referenzzählung keinen Strich durch die Rechnung machen soll

Apollonius 13. Aug 2009 10:48

Re: Interfacelisten: Objekt wird bei remove freigegeben
 
@himitsu: Auch hier gibst du durch das abschließende _Release das Objekt schon frei.
Edit: Hoppla, zu früh geschrien. Das ist ja ein l.Free am Ende. :oops:

himitsu 13. Aug 2009 10:59

Re: Interfacelisten: Objekt wird bei remove freigegeben
 
Zitat:

Zitat von Apollonius
@himitsu: Auch hier gibst du durch das abschließende _Release das Objekt schon frei.

das ist ja auch so geplant :)
abgesehn, daß _Release das Objekt nicht freigibt, wenn noch irgendwo eine Referenz existiert
und durch _AddRef die InterfaceList das Objekt auch nicht freigibt, da ja der Referenzzähler danach nur von 2 auf 1 fällt und demnach nicht freigegeben wird.

mjustin 13. Aug 2009 11:51

Re: Interfacelisten: Objekt wird bei remove freigegeben
 
Zitat:

Zitat von Stevie
Grundregel, wenn du nicht die Referenzzählung außer Kraft setzen oder anderweitig "austricksen" willst: niemals mit Objektreferenzen sondern immer mit Interfacereferenzen arbeiten, wenn dir die Referenzzählung keinen Strich durch die Rechnung machen soll

Gute Regeln können so einfach sein :)

Also statt

Delphi-Quellcode:
var
  L: TInterfaceList;
  X: TTest;
einfach bei den Typen öfter ein I statt eines T verwenden:

Delphi-Quellcode:
var
  L: IInterfaceList;
  X: IMyInterface;

Manche Bibliotheken funktionieren sogar besser, wenn für die Erzeugung von Instanzen Interface-Variablen benutzt werden.
Zum Beispiel kann es leicht zu Access Violations geben, wenn man für eine dynamisch erzeugte TXMLDocument Instanz den Variablentyp IXMLDocument (statt TXMLDocument) benutzt. (siehe http://edn.embarcadero.com/article/29241).



Cheers,


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:05 Uhr.
Seite 1 von 2  1 2      

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