AW: Referenzen auf ungültige Objekte
Zitat:
Zitat:
Zitat:
[edit] Übrigens, wenn ich keinen Denkfehler habe, müsste sich mein Code sogar so erweitern lassen, dass Objekte, auf die keine Referenz mehr existiert, automatisch zerstört werden (also so ähnlich wie Interfaces). Durchaus eine spannende Sache... [/edit] |
AW: Referenzen auf ungültige Objekte
Ich halte die Idee, die Referenzen aufzulisten, für einen nicht unproblematischen Weg:
Mein Vorschlag: (Globale) Events anbieten, welches bei Erstellung und Freigabe eines Objekts aufgerufen werden und eine Referenz erhalten. Mit Hilfe der Events könnte man dann (wenn man möchte) Listen von Objekten verwalten, um damit die Existenz von Objekten zu prüfen (oder andere coole Sachen machen). Alle Anderen bekommen dann als Overhead nur, dass während der Erstellung und Freigabe von Objekten geprüft wird, ob die Events gesetzt sind. Das sollte doch im allgemeinen Speicherverwaltungstrubel untergehen :gruebel: :duck: |
AW: Referenzen auf ungültige Objekte
Es ist eine Weile her dass ich mit Interfaces experimentiert habe, hatte aber das von mir gewünschte Verhalten nur mit TInterfacedPersistent, welches für den vorgeschlagenen Ansatz freilich unbrauchbar ist.
Diese automatische Freigabe von Objekten nur weil der Compiler weiß dass ein Objekt nicht mehr benötigt wird, bzw. die Notwendigkeit Objekte dann doch manuell freigeben zu müssen weil die Referenzen global gehalten wurden und aus Events erreichbar waren ... hier dann den Überblick zu behalten was nicht freigegeben werden darf(oder kann) und was freigeben werden muss hat mir die Sache damals dermaßen verleidet, dass ich mich für virtuelle Implementierungen entschieden habe. Sorry für OT, hat ja eigentlich mit dem Thema nicht wirklich etwas zu tun. |
AW: Referenzen auf ungültige Objekte
Ich wieder...
Meine Verfahrensweise war ja folgende: Bei Freigabe eines Objektes untersuche ich alle anderen Objekte per RTTI, ob diese mit einer Objekteigenschaft mein Objekt referenzieren. Dann werden diese betreffenden Objekteigenschaft auf nil gesetzt und danach mein Objekt freigegeben. Im Grunde funktioniert das (ich arbeite nicht mit Threads) absolut perfekt. ABER es ist extrem langsam. Ein paar "Optimierungen" musste ich jetzt entfernen, so dass ich die Sache auch nicht beschleunigen kann. Daher habe ich nun doch eine Observer-Lösung im Auge, möchte das aber auch soweit in meinem App-Framework automatisieren, dass ich nicht zu viel von Hand regeln muss. Heute Abend schaue ich mir nochmal NamenLozers Lösung an. Vielleicht verstehe ich das ja wenn ich mein Delphi zur Hand habe (so rein theoretisch habe ich keine Chance) und vielleicht lässt sich das ja gut für mich nutzen. Eine Frage mal grundsätzlich: WANN wird denn eigentlich genau der Referenzzähler eines Objektinterface erhöht und verringert? Macht das der Compiler, wenn ein Objekt an eine Methode übergeben bzw. wenn diese beendet wird und außerdem auch wenn man ObjA := ObjB schreibt? Und das Objekt wird (erst) bei Ref=0 (tatsächlich) freigegeben? Irgendwie tue ich mich mit den Interfaces immer noch zu schwer... :duck: |
AW: Referenzen auf ungültige Objekte
Objekte haben keinen Referenzzähler (standardmäßig), also macht Delphi da auch nichts, beim Kopieren/Freigeben der Objektreferenz.
Das Einzig umständliche ist, daß man interfaces noch "zusätzlich" erstellen/verwalten muß. Es wäre ja zu schön, wenn man aus einem Objekt (automatisch) ein Interface generieren könnte. (aber wenn ich mir das grad überlege ... ich glaub das wäre möglich ... muß ich mal sehn, hab eh vor zu versuchen endlich mal einen Precompiler ins Delphi reinzubekommen) |
AW: Referenzen auf ungültige Objekte
Zitat:
|
AW: Referenzen auf ungültige Objekte
Aber nur bei einem "Interface", aber nicht bei Objekten (es sei denn ein Interface wurde angegeben und die eingebetteten Objekte werden über das Interface referenziert/angesprochen)
|
AW: Referenzen auf ungültige Objekte
Also ist es so?
Ich habe 3 Interfaces I1, I2, I3 und erzeuge "in jedes" ein Objekt (O1, O2, O3). Alle Interfaces haben den Referenzzähler 1. MyProcedure(I2) erhöht für I2 den Referenzzähler auf 2 bis die Prozedur verlassen wird. I4 := I2 erhöht wieder für I2 den Referenzzähler auf 2? I2.Free löst das objekt dann noch nicht auf. Über I4 wäre es noch ansprechbar? Aber was wäre wenn man I1 := I3 zuweist? O1 würde aufgelöst und I3 der Referenzzähler erhöht? Die Objekte selbst sollten dann aber auf keinen Fall händisch aufgelöst werden (also auch nicht aus einer TObjectList mit OwnObjects entfernt werden). Wenn es einem nicht darum geht, eine Art Mehrfachvererbung zu nutzen (unterschiedliche Objekte mit gleichen Methoden), sondern nur die Referenzierungen sinnvoll behandeln will, dann ist das schon recht kompliziert und aufwendig. Meine Überlegung war: Wenn für Interfaces die Referenzen vom Compiler überwacht und verwaltet werden, dann sollte das grundsätzlich ja auch für normale Objekte möglich sein. Ok, die müssten noch eine Referenzliste o.ä. erhalten, aber dann würde das automatisiert im Hintergrund ablaufen können. Philips Lösung sieht ja schon richtig gut aus (ich werde das heute Abend mal ansehen, auch in Bezug auf Objektreferenzen in Propertys). Wenn der Compiler so etwas aber nativ verwurschteln würde wäre m.E. eine der größten Schwächen von Delphi abgestellt. Projekte ließen sich viel leichter realisieren, da ALLE Zugriffe auf aufgelöste Objekte auf NIL zugreifen würden (statt auf zufällige Speicherstellen). |
AW: Referenzen auf ungültige Objekte
Man kann Interfaces auch ohne Referenzzählung laufen lassen.
Dann muß man entweder noch Zugriff auf die Objektreferenz haben oder man baut sich eine "gib dich frei"-Methode mit ein, worüber man das Interface dann freigeben kann. Aber da ist zu beachten, daß bei freigabe alle übrigen Referenzen, sollten noch welche vorhanden sein, zum Absturz führen können, wenn diese feigegeben werden und Delphi dem Interface (welches ja nicht mehr existiert) dieses mitteilen will. PS: Deswegen speichert man sich manchmal auch als Pointer gecastete Interfacereferenzen, da dort keine automatische Referenzzählung auftritt. Aber: Nimm dir besser eine TInterfaceList, in dieser hälst du dir eine Referenz und so immer Eine übrig ist, wird das Interface frühestens dann freigegeben, wenn diese InterfaceListe ebenfalls seine Referenzen freigibt. |
AW: Referenzen auf ungültige Objekte
@stahli:
Wenn ich dich richtig verstehe, dann willst du für deine Objekte das gleiche Verhalten wie in einer Datenbank bei ForeignKeys. Die können z.B. bei einer Löschung des Basis-Datensatzes alle verlinkten Datensätze entsprechend aktualisieren und dort die Referenz z.B. auf NULL setzen. Ein Ansatz dazu wäre folgender:
Delphi-Quellcode:
Jetzt kannst du bei Bedarf die Person aus der Turnier-Instanz holen und bekommst nur dann eine gülitge Instanz, wenn es diese Person auch noch in der GlobalenObjektListe enthalten ist.
type
TTurnier = class private fPersonID : integer; procedure SetPerson( const Value : IPerson ); function GetPerson : IPerson; public property Person : IPerson read GetPerson write SetPerson; end; procedure SetPerson( const Value : IPerson ); begin fPersonID := Value.ID; end; function GetPerson : IPerson; begin Result := GlobaleObjektListe.GetPerson( fPersonID ); end; Diese GlobaleObjektListe gibt die Instanzen allerdings nicht frei, sondern vergisst diese einfach nur (IPerson => Interface). Dann sollte es nicht mehr rumsen und die Referenzen sind sauber. Und dieses Rumgeeiere mit RTTI kannst du dir sparen ;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10: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