AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Referenzen auf ungültige Objekte

Ein Thema von stahli · begonnen am 14. Mär 2011 · letzter Beitrag vom 2. Mär 2012
Antwort Antwort
Seite 1 von 6  1 23     Letzte » 
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.236 Beiträge
 
Delphi 10.4 Sydney
 
#1

Referenzen auf ungültige Objekte

  Alt 14. Mär 2011, 14:31
(Ich habe es schon mal angesprochen, will es aber nochmal strukturierter angehen.)

Das Problem:
- Objekt O ist instantiiert.
- Eigenschaft X.MyO zeigt auf O.
- Variable MyO zeigt ebenfalls auf O.

Wird Objekt O freigegeben (vielleicht sogar mit FreeAndNil(O)) zeigen X.MyO und MyO auf einen "ungültigen" Speicherbereich.

Eine Lösung sollen Interfaces bzw. Referenzzähler bieten. Durch diese wird O tatsächlich erst freigegeben, wenn die Referenzen von X.MyO und MyO quasi abgemeldet werden.
Wie ich das verstanden habe, funktioniert dies so mit Interfaces im Delphi sowie auch mit der GarbageCollection im .NET.
Das läuft auch unter dem Begriff "SmartPointer".

Soweit richtig?

Das ist aber noch nicht der Ansatz, den ich mir wünschen würde.
Ich hätte gern, dass X.MyO und MyO bei O.Free automatisch auf nil gesetzt werden.

Derzeit löse ich das in meinem Projekt händisch (durch die Verwaltung von eigenen Listen), da kann es jedoch passieren, dass ich einige Objekte vergesse und später nachtragen muss.

Daher zwei Fragen:

1) Könnte/Sollte Delphi (optional) nicht eine Funktion bieten, die eine solche Verwaltung übernimmt?
Man könnte Objekte regestrieren, die "überwacht" werden sollen: RegisterValidObject(O) Das Objekt O wird in eine Liste aufgenommen. Wird das Objekt freigegeben, wird es aus der Liste entfernt.
Dann könnte man mit IsValidObject(X.MyO) bzw. IsValidObject(MyO) prüfen, ob das Objekt noch gültig (noch in der Kontroll-Liste enthalten) ist.
Das wäre so ähnlich zu sehen, wie Assigned(X.MyO) , wobei nicht nur auf nil geprüft wird, sondern auf die Existenz des referenzierten Objektes.

2) Weiterhin wäre es wünschenswert, wenn die Referenzen automatisch "genilt" würden.
Dazu müsste wohl zusätzlich verwaltet werden, ob eine Variable, ein Objektfeld oder eine Objekteigenschaft das zu überwachende Objekt referenziert.
Bei der Freigabe von O müssten alle diese registrierenten Referenzen automatisch auf nil gesetzt werden.


Im Moment realisiere ich den zweiten Weg selbst durch Nutzung der neuen RTTI-Möglichkeiten.
Ich durchsuche meine Objekte nach überschreibbaren Eigenschaften, die auf Objekte zeigen, prüfe, ob das betreffende Objekt noich existiert und setze andernfalls diese Eigenschaft auf nil.
Das funktioniert, ist aber auf meine eigenen Objekte beschränkt und berücksichtigt keine Variablenreferenzen.

Eine Delphi-native Lösung hielte ich für nützlich und grundsätzlich wohl auch für realisierbar.
Wie seht Ihr das?
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
WM_CLOSE

Registriert seit: 12. Mai 2010
Ort: königsbronn
398 Beiträge
 
RAD-Studio 2009 Pro
 
#2

AW: Referenzen auf ungültige Objekte

  Alt 14. Mär 2011, 14:35
Man könnte ein TSmartObject einführen, aber dann müssten zwangsweise alle Klassen, die den SmartPointer unterstützen von ebendieser Klasse abstammen.
Ich weiß nicht, ob man mit der RTTI so weit kommt.
  Mit Zitat antworten Zitat
r2c2

Registriert seit: 9. Mai 2005
Ort: Nordbaden
925 Beiträge
 
#3

AW: Referenzen auf ungültige Objekte

  Alt 14. Mär 2011, 20:05
Wird Objekt O freigegeben (vielleicht sogar mit FreeAndNil(O)) zeigen X.MyO und MyO auf einen "ungültigen" Speicherbereich.
richtig.

Zitat:
Eine Lösung sollen Interfaces bzw. Referenzzähler bieten.
Ja, kann man dafür nehmen.

Zitat:
Durch diese wird O tatsächlich erst freigegeben, wenn die Referenzen von X.MyO und MyO quasi abgemeldet werden.
So in etwa. Ja.

Zitat:
Wie ich das verstanden habe, funktioniert dies so mit Interfaces im Delphi sowie auch mit der GarbageCollection im .NET.
Is AFAIK anders realisiert, aber so kannst du dirs vorstellen.

Zitat:
Das läuft auch unter dem Begriff "SmartPointer".
Den Begriff "smart pointer" kenn ich eher aus C++. Da beschreibt er ein Konzept mit ähnlichem Zweck. Interfaces würde ich aber erstmal nicht als smart pointer bezeichnen, auch wenn der Effekt ähnlich ist.

Zitat:
1) Könnte/Sollte Delphi (optional) nicht eine Funktion bieten, die eine solche Verwaltung übernimmt?
Man könnte Objekte regestrieren, die "überwacht" werden sollen: RegisterValidObject(O) Das Objekt O wird in eine Liste aufgenommen. Wird das Objekt freigegeben, wird es aus der Liste entfernt.
Dann könnte man mit IsValidObject(X.MyO) bzw. IsValidObject(MyO) prüfen, ob das Objekt noch gültig (noch in der Kontroll-Liste enthalten) ist.
Das wäre so ähnlich zu sehen, wie Assigned(X.MyO) , wobei nicht nur auf nil geprüft wird, sondern auf die Existenz des referenzierten Objektes.
Prinzipiell möglich. Das ist aber doch genau das, was du momentan tust. Oder hab ich dich da falsch verstanden?

Zitat:
2) Weiterhin wäre es wünschenswert, wenn die Referenzen automatisch "genilt" würden.
Dazu müsste wohl zusätzlich verwaltet werden, ob eine Variable, ein Objektfeld oder eine Objekteigenschaft das zu überwachende Objekt referenziert.
Bei der Freigabe von O müssten alle diese registrierenten Referenzen automatisch auf nil gesetzt werden.
Und das ist ohne erheblichen Aufwand eben nicht möglich. Können die neuen records eigentlich auch Destruktoren haben? Wenn ja, könnte man sich damit mehr oder weniger die oben erwähnten Smart Pointer nachbauen. Das wäre dann zumindest sowas Ähnliches.

Zitat:
Eine Delphi-native Lösung hielte ich für nützlich und grundsätzlich wohl auch für realisierbar.
Wie seht Ihr das?
Jetzt kommt meine eigentlich Antwort auf deine Frage: Ich halte das für in den meisten Fällen unnötig. Wenn du einen sauberen Ansatz hast, brauchst du das alles nicht. Insbesondere halte ich deine Workarounds für Frickellösungen, die mehr Probleme schaffen als lösen. Ich will dein Vorhaben damit nicht generell verteufeln. Manchmal braucht man eben - leider - Frickllösungen. Ich denke aber, du solltest dir nochmal genau überlegen, ob du nicht ein konzeptionelles Problem hast. Sag mal was zu deinen Objekten. Welche sind es, warum brauchst du die und warum kommt es zu diesen Problemen mit dem Freigeben (also nicht technisch, sondern inhaltlich gesehen)? Vielleicht gibts ja eignen besseren Weg...

mfg

Christian
Kaum macht man's richtig, schon klappts!
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
16.913 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Referenzen auf ungültige Objekte

  Alt 14. Mär 2011, 20:50
Mach es doch wie auch tausendfach in der VCL gemacht wird. Wenn du eine Zeiger auf ein objekt hast trägst du dich in die Notify-Liste für die Freigabe ein. Diese wird vor der Freigabe des Objekts durchlaufen und das andere Objekt kann seinen Member nillen.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
WM_CLOSE

Registriert seit: 12. Mai 2010
Ort: königsbronn
398 Beiträge
 
RAD-Studio 2009 Pro
 
#5

AW: Referenzen auf ungültige Objekte

  Alt 14. Mär 2011, 21:32
man sollte auch nicht vergessen, dass die "Pointer" in -NET keine klassischen Cardinal sind, sondern Klassen, so wie fast alles in .NET.
Da lassen sich Zeiger wunderbar um einen Notifier erweitern, dass allen anderen Zeigern sagt, dass sie jetzt ungültig sind.
Aber in Delphi sind die Zeiger ja Passiv.
Man könnte über Records diese .NET-Zeiger nachbauen, aber mit der IDE kann man dann vermutlich nicht mehr rechnen:
d.h. Kein InteliSense usw. Das Prob hatten wir scon mit den neuen Generics - andauernd fehler, die gar keine waren...
Und die Destruktoren für Records muss man dem Compiler auch erst mal einhämmern.(Aber gehen tut es)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.236 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Referenzen auf ungültige Objekte

  Alt 14. Mär 2011, 22:07
@r2c2:
Mein Projekt arbeitet komplett mit Objekten. Diese beinhalten die Daten und die Geschäftslogik.
Obendrauf gibt es eine GUI-Ebenene zur Darstellung und Bearbeitung der Daten.

Die Objekte halten Referenzen aufeinander (ein Verein verwaltet eine Liste von Mitgliedern, jedes Mitglied enthält eine Instanz einer Person. Jedes Spiel hat zwei Spielparteien. Jede Spielpartei hat ein oder zwei Spieler. Jeder Spieler hat eine Referenz (keine Instanz) auf eine Person. Eine Funktion ermittelt übergeordnete Komponenten - Z.B. ein Turnier, in dem ein bestimmtes Spiel enthalten ist).

Wird z.B. ein Personenobjekt gelöscht, müssen die anderen Komponenten, die eine Referenz darauf enthalten, diesen ungültigen Zeiger nilen.

Ich habe eine Lösung aus den beiden o.g. Punkten 1 + 2 realisiert. Dies funktioniert für meine Objekte schon sehr gut.

ABER ich halte z.B. auch in einem dynamischen Formular in einer Eigenschaft eine Referenz z.B. auf ein Turnierobjekt.

Wird dieses Turnierobjekt freigegeben, muss ich diese Formulareigenschaft explizit nilen - sonst geht das ggf. schief.

Wenn es dafür eine allgemeine Lösung gäbe, fände ich das hilfreich.


@Bernhard:
Das gibt es aber doch nur in Listen, meine ich!?
Oder kannst Du eine Lösung für mein o.g. Beispiel zeigen?


@WM_CLOSE:
Der Umweg über Records hört sich kompliziert an.
Ich hatte die Hoffnung, dass der Compiler (optional) einfach eine Liste der Referenzen anlegt und bei späteren Zugriffen "korrigiert".
Im Grunde mache ich das ja schon für meine Objekte, das ist aber noch nicht allgemein genug einsetzbar.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#7

AW: Referenzen auf ungültige Objekte

  Alt 15. Mär 2011, 04:14
Ich kenne dein Konzept nicht, halte aber Referenzen, die -wupps- plötzlich invalid werden können, für kein gutes Design, auch wenn ich die Referenzen per Notify auf Nil setzen kann.

Deine Programmlogik kann dann an beliebigen Stellen gegen die Wand fahren. Du weisst nie, wann das der Fall sein wird, vielleicht sogar während einer elementaren Operation...

Wenn Du dir sicher bist, das dieser verteilte Zugriff
Du könntest diese Objekte auch über das Handle-Konzept realisieren:
Du instantiierst ein Objekt und bekommst von einer zentralen Vewaltung ein Handle zurück.

Du verwendest das dahinterliegende Objekt, indem Du es per Handle anforderst und automatisch gegen instantane Freigabe sperrst. Zum Ende der Verwendung gibst Du die Anforderung wieder frei.

Die Freigabe ist dann ein "gib es dann frei, wenn alle Anforderungen zurückgegeben wurden".

Du müsstest im Code nur dafür sorgen, das die Rückgabe so schnell wie möglich geschieht.

Delphi-Quellcode:
MyObject := ObjectManager.AcquireObjectByHandle(MyHandle);
If MyObjecty<>Nil Then
  Try
    DoSomethingWith(MyObject);
    DoSomethingElseWith(MyObject);
  Finally
    ObjectManager.ReleaseObjectByHandle(MyHandle);
    // MyObject ist nun nicht mehr gültig
  End
Else
  Raise EHonestlyIDontKnowHowToHandleThis.Create;
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Lemmy

Registriert seit: 8. Jun 2002
Ort: Berglen
2.293 Beiträge
 
Delphi 10.3 Rio
 
#8

AW: Referenzen auf ungültige Objekte

  Alt 15. Mär 2011, 07:13
Guten Morgen,

was spräche denn dagegen hier das Observer-Pattern einzusetzen? Der Observer wird vom Subject informiert wenn dieses freigegeben wird. Damit kann der Observer entsprechend reagieren und die Referenz entfernen...

Grüße
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.332 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Referenzen auf ungültige Objekte

  Alt 15. Mär 2011, 13:19
Mach es doch wie auch tausendfach in der VCL gemacht wird. Wenn du eine Zeiger auf ein objekt hast trägst du dich in die Notify-Liste für die Freigabe ein. Diese wird vor der Freigabe des Objekts durchlaufen und das andere Objekt kann seinen Member nillen.
Guten Morgen,

was spräche denn dagegen hier das Observer-Pattern einzusetzen? Der Observer wird vom Subject informiert wenn dieses freigegeben wird. Damit kann der Observer entsprechend reagieren und die Referenz entfernen...

Grüße
Das ist ein klassischer Fall für das Observer-Pattern und in der VCL auch so realisiert.
In allen existierenden Objekten nach einer Referenz zu suchen, halte ich für einen Designfehler.
  Mit Zitat antworten Zitat
r2c2

Registriert seit: 9. Mai 2005
Ort: Nordbaden
925 Beiträge
 
#10

AW: Referenzen auf ungültige Objekte

  Alt 15. Mär 2011, 17:01
Mein Projekt arbeitet komplett mit Objekten. Diese beinhalten die Daten und die Geschäftslogik.
Obendrauf gibt es eine GUI-Ebenene zur Darstellung und Bearbeitung der Daten.
Das ist soweit vollkommen normal.

Zitat:
ein Verein verwaltet eine Liste von Mitgliedern,
OK.

Zitat:
jedes Mitglied enthält eine Instanz einer Person.
Huch. Wieso das? Ich denke doch eher ein Mitglied *ist* eine Person.

Zitat:
Jedes Spiel hat zwei Spielparteien. Jede Spielpartei hat ein oder zwei Spieler.
OK.

Zitat:
Jeder Spieler hat eine Referenz (keine Instanz) auf eine Person.
Und wieder: Ich denke eher ein Spieler *ist* eine Person.

Zitat:
Eine Funktion ermittelt übergeordnete Komponenten - Z.B. ein Turnier, in dem ein bestimmtes Spiel enthalten ist).
Versteh ich nicht.

Zitat:
Wird z.B. ein Personenobjekt gelöscht, müssen die anderen Komponenten, die eine Referenz darauf enthalten, diesen ungültigen Zeiger nilen.
Hier solltest du dir genau überlegen, was die Semantik des Löschens ist. Warum wird eine Person überhaupt gelöscht? Und wer tut das? Und was genau soll da passieren? Solche Probleme lösen sich oft durch die Beantwortung der folgenden Fragen:
- Zu wem gehört das Objekt?
- Wer ist dafür zuständig es frei zu geben?
- Wann und warum wird das Objekt freigegeben?

Im Idealfall hat man die folgenden beiden Fälle:
- Ein Objekt wird nur innerhalb einer Methode benutzt ==> Dann Create und Free mit try..finally in der Methode
- Ein Objekt gehört zu einem anderen Objekt (Komposition) ==> Dann create im Konstruktor und Free im Destruktur.

Dadurch ergeben sich Baumstrukturen von "gehört-zu-Beziehungen" und man hat i.d.R. keine Probleme mit der ganzen Freigeberei. Wenn man jetzt doch mal "außer der Reihe" ein Objekt freigeben will, stellt sich wie immer die Frage wer dafür zuständig ist und ob der weiß, wo überall Referenzen rumfliegen. Wenn du n Klassendiagramm postest, könnt ich mal drübergucken. Ich vermute, dass da was mit den Zuständigkeiten nicht passt. Observerpattern udn Events wurden bereits genannt. Das sind Möglichkeiten die Kopplung zu reduzieren und so das Problem gar nicht erst entstehen zu lassen.

//Nachtrag:
@WM_CLOSE: Seit wann sind Pointer in .NET Klassen? Ich hab zwar schon lang kein .NET mehr gemacht, aber das wär mir neu.

mfg

Christian
Kaum macht man's richtig, schon klappts!

Geändert von r2c2 (15. Mär 2011 um 17:13 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:32 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf