Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Freigabe von Objekten (Observerpattern) (https://www.delphipraxis.net/180452-freigabe-von-objekten-observerpattern.html)

TheGroudonx 21. Mai 2014 12:46

Freigabe von Objekten (Observerpattern)
 
Hallo,

ich habe folgendes Problem:

Infos:

Ich besitze ein ObjektX mit der Vererbung class(TInterfacedObject, IInterfaceX).
Dessen Referenz übergebe ich an ein normales Objekt.
Dieses normale Objekt meldet nun über das Interface Veränderungen an das ObjektX.

Problem:

Wenn das normale Objekt(befindet sich in einem Array) mit .free /.freeandnil / .destroy freigegeben wird,
wird das ObjektX scheinbar mitgelöscht, wodurch es beim Erstellen eines neuen
normales Objekts zu einer Zugriffsverletzung kommt. Ich konnte bisher etwas bezüglich eines Referenzzählers herrausfinden,
jedoch nicht wie die automatische Löschung umgehbar ist. Bisher bin ich deswegen gezwungen, auf .free zu verzichten.

Wenn ihr hilfreiche Tipps habt lasst es mich wissen :-D

Namenloser 21. Mai 2014 13:03

AW: Freigabe von Objekten (Observerpattern)
 
Willkommen in der DP :dp:
Zitat:

Wenn das normale Objekt(befindet sich in einem Array) mit .free /.freeandnil / .destroy freigegeben wird,
wird das ObjektX scheinbar mitgelöscht, wodurch es beim Erstellen eines neuen
normales Objekts zu einer Zugriffsverletzung kommt.
Den Abschnitt verstehe ich nicht ganz. Was ist das „Objekt“, und was ist das „ObjektX“? Ist beides das gleiche Objekt, sind es unterschiedliche Objekte? Wo wird was „mitgelöscht“ und was heißt hier „scheinbar“?

Grundsätzlich kann man die automatische Freigabe eines Objektes hinter einem Interface verhindern, indem man manuell seine Methode
Delphi-Quellcode:
AddRef
aufruft. Dadurch wird der Referenzzähler um 1 erhöht und somit nicht 0 (was eine Zerstörung des Objekts auslösen würde), nachdem das letzte Interface gelöscht wurde.

Aber, meine Empfehlung: Wenn Interfaces, dann konsequent. Nicht Interfaces mit normalem Objektzugriff mischen. Das macht nur Kopfschmerzen. Also stell lieber die Stellen, wo du noch direkt auf das Objekt zugreifst, auch auf Interfaces um, dann hast du das Problem nicht und die Referenzzählung erledigt alles automatisch (nur bei zyklischen Referenzen musst du aufpassen).

Stevie 21. Mai 2014 15:02

AW: Freigabe von Objekten (Observerpattern)
 
Zitat:

Zitat von TheGroudonx (Beitrag 1259627)
Ich besitze ein ObjektX mit der Vererbung class(TInterfacedObject, IInterfaceX).
Dessen Referenz übergebe ich an ein normales Objekt.

...


Wenn das normale Objekt freigegeben wird, wird das ObjektX scheinbar mitgelöscht, wodurch es beim Erstellen eines neuen
normales Objekts zu einer Zugriffsverletzung kommt.

Speicherst du dein ObjectX als Objektvariable oder als Interfacevariable? Im ersten Fall hast du also nicht die Referenzzählung getriggert, so dass dein Objekt, das du es als Interface übergibst die einige gezählte Referenz hält, wirds freigegeben, tickert der RefCount auf 0 und dein ObjectX wird freigegeben.

Sir Rufo 21. Mai 2014 16:46

AW: Freigabe von Objekten (Observerpattern)
 
Hier mal veranschaulicht
Delphi-Quellcode:
type
  IObjectX = interface
  end;

  TObjectX = class( TInterfacedObject, IObjectX )
  end;

procedure Test;
var
  LObj : TObjectX;
  LIntf : IObjectX;
begin
  LObj := TObjectX.Create; // RefCount ist 0
  LIntf := LObj; // RefCount+1 -> 1
  LIntf := nil; // RefCount-1 -> 0 -> Instanz wird freigegeben
  LObj.Free; // rumms, ist ja nix mehr da an der Referenz
end;

TheGroudonx 22. Mai 2014 15:55

AW: Freigabe von Objekten (Observerpattern)
 
Danke erstmal,

der genauere Code ist in 4 Units eingeteilt.

Hauptunit beinhaltet das ObjektX und das ObjektN
Die Unit von ObjektN speichert die Referenz auf das ObjektX als Interface


UHaupt:
ObjektN: Array of TObjektN;
ObjektX: TObjektX;

Code der Zugriffsverletzung verursacht:
ObjektN[x] := TObjektN.create(ObjektX);
ObjektN[x].freeandnil;
ObjektN[x] := TObjektN.create(ObjektX); <==



UObjektX:
TObjektX = class(TInterfacedObject, IObserverObjektX)



UObjektN:
TObjektN = class
var
ObjektX: IObserverObjektX;


UObserverObjektX
IObserverObjektX = Interface(IInterface)

Dejan Vu 22. Mai 2014 16:01

AW: Freigabe von Objekten (Observerpattern)
 
Entweder nur mit der Instanz oder nur mit dem Interfacezeiger arbeiten. *NIE* nicht niemals kombiniert. Warum, hat seine Durchlaucht Rufo schon wunderbar erklärt.

TheGroudonx 11. Jun 2014 09:36

AW: Freigabe von Objekten (Observerpattern)
 
Danke für die Antworten.

Ich habe das Problem jetzt so gelöst, dass ich eine weitere Variable des Interfaces gespeichert habe, wodurch der Referenzzähler nichtmehr auf 0 geht, wenn ein Objekt gefreet wird, welches eine Interface-Referenz gespeichert hat.

himitsu 11. Jun 2014 09:51

AW: Freigabe von Objekten (Observerpattern)
 
Man kann natürlich auch mit Intf._AddRef rumspielen, oder die Referenzzählung direkt beeinflussen.

Siehe TComponent, welches Interfaces ohne Referenzzählung implementiert, wobei die Freigabe der Instanz also standardmäßig weiterhin ausschließlich über den Owner und .Free geregelt wird, oder eventuell auch über eingebettete VCL-Interfaces, welche die Kontrolle übernehmen.




Aber Grundsätzlich ist dein Vorgehen eher "falsch".

Entweder du nutzt das Objekt als Objekt und verwendest keine Interfaces, oder du nutzt das Objekt ausschließlich nur noch über Interface-Referenzen und schon gibt es keine Probleme damit.

Sir Rufo 11. Jun 2014 13:59

AW: Freigabe von Objekten (Observerpattern)
 
Delphi-Referenz durchsuchenTInterfacedPersistent ist schon eine Implementierung ohne Referenzzählung.
Ist halt nur doof, wenn man die Instanz freigibt und irgendjemand hat da noch die Finger drauf :stupid:


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