Entwickler-Ecke

Sonstiges (Delphi) - Prüfen ob ein Objekt noch existiert?


matze - Do 17.09.09 11:45
Titel: Prüfen ob ein Objekt noch existiert?
Hallo.

Ich habe ein etwas blödes Problem:
In meiner Anwendung gibt es recht viele Objekte, die sich auch untereinander "verlinken". Jetzt kann es sein, dass ein Objekt gelöscht wird.
Wie kann ich denn in meinen anderen Objekten abfragen, ob es das Objekt, auf das ich gerade zugreifen will, noch gibt?
Das Feld mit dem Objekt kann ja nicht auf nil gesetzt werden, demzufolge fällt auch eine Überprüfung mit Assign aus oder?

Wie mache ich sowas denn also richtig?

Danke,
Matze


Xentar - Do 17.09.09 12:21

user profile iconmatze hat folgendes geschrieben Zum zitierten Posting springen:
Das Feld mit dem Objekt kann ja nicht auf nil gesetzt werden, demzufolge fällt auch eine Überprüfung mit Assign aus oder?

Wieso kann das nicht auf nil gesetzt werden?
Gib die doch einfach mit FreeAndNil frei.

Delphi-Quelltext
1:
FreeAndNil(FMyObject);                    


matze - Do 17.09.09 12:36

Weil das Objekt nicht immer von dem Objekt gelöscht wird, das es auch benutzt.


Narses - Do 17.09.09 12:50

Moin!

Man kann grundsätzlich nicht rausfinden, ob ein Pointer auf "gültigen" Speicher zeigt (also ob da ein anderes Objekt "lebt"). Ansatz: Registriere alle Objekte in einer (klassen-)globalen Objekt-Liste, so dass diese auch der Eigentümer der Objekte ist. Wenn du ein Objekt freigibst, dann erledigst du das über diese globale Liste. Willst du prüfen, ob eine Referenz noch gültig ist, schaust du in der Objekt-Liste nach. :idea: Ist nicht unbedingt effizient, aber funktioniert. :nixweiss:

cu
Narses


matze - Do 17.09.09 13:18

Ja das ginge auch.
Was passiert denn, wenn ich trotzdem auf das Objekt zugreife? Dann bekomme ich doch ne Access Violation oder? Aber die kann ich doch mit try except abfangen oder nicht?


Narses - Do 17.09.09 13:22

Moin!

user profile iconmatze hat folgendes geschrieben Zum zitierten Posting springen:
Was passiert denn, wenn ich trotzdem auf das Objekt zugreife? Dann bekomme ich doch ne Access Violation oder? Aber die kann ich doch mit try except abfangen oder nicht?
Nein, du kriegst nicht automatisch eine Exception. Bestenfalls liegen die Daten des Objekts noch an der Stelle im RAM, so dass der Zugriff zu klappen scheint, schlechtestenfalls sind die Daten überschrieben und du greift auf "nicht initialisierten" Speicher zu - was dabei passiert, ist nicht vorhersagbar. :nixweiss:

cu
Narses


matze - Do 17.09.09 13:44

na klasse :-( dann bleibt also nur der Weg über eine Liste. Oder gibts da noch andere Möglichkeiten?


Martok - Do 17.09.09 14:30

Naja... du könntest eine Referenz-Zählung a la Interfaces bauen, statt direkt die Objekte freizugeben. Musst dann nur ab und zu mal garbage collecten (oder wie auch immer das Verb dazu heißt).

Ich mach das allerdings meistens so, dass sich die Objekte selbst merken, wer Referenzen auf sie hält. Beim Freigeben wandert dann eine Reihe von Notifications raus "Achtung, mich gibts gleich nicht mehr".
So ähnlich macht das ja auch die VCL.


matze - Do 17.09.09 14:42

und die Objekte, die Referenz auf das andere halten, müssen sich dann bei diesem Anmelden oder wie?
Und wie lässt du diese "Meldung" versenden?


Martok - Do 17.09.09 15:59

user profile iconmatze hat folgendes geschrieben Zum zitierten Posting springen:
und die Objekte, die Referenz auf das andere halten, müssen sich dann bei diesem Anmelden oder wie?

Jap.

Die Referenzen sind Properties einer Klasse, so dass sich der Setter drum kümmern kann bei der neuen an- und der alten abzumelden. Muss man nur dran Denken, beim Freigeben dieses Property auf nil zu setzen, sonst hat man das gleiche Problem nur anders rum ;)

user profile iconmatze hat folgendes geschrieben Zum zitierten Posting springen:
Und wie lässt du diese "Meldung" versenden?

Die VCL kennt unterhalb von TComponent dafür NotifyComponent & Konsorten, bei mir sind das einfach nur Aufrufe an eine protected deklarierte Methode ("RemoveReference(Ref: TReferredObject)").
Beim Freigeben eines Referenzierten Objekts kann man dann einfach die Liste durchgehen und diese Methode aufrufen.


Falls ich mich grad wieder verquer ausgedrückt hab, sag bescheid. Ich hack dann mal schnell eine Demo, wie ich das meine.


matze - Do 17.09.09 16:52

Nee das kapier ich schon :-)
Hmmm... Dann werd ich mir das mal durch den Kopf gehen lassen.

Aber ich seh schon, dass ich ohne eine Liste nicht auskommen werde.

Danke an alle!
Matze