AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi COM: TInterfacedObject-Nachfahren explizit freigeben
Thema durchsuchen
Ansicht
Themen-Optionen

COM: TInterfacedObject-Nachfahren explizit freigeben

Ein Thema von Udontknow · begonnen am 11. Okt 2002 · letzter Beitrag vom 14. Okt 2002
Antwort Antwort
Seite 1 von 2  1 2      
Udontknow

Registriert seit: 17. Jun 2002
223 Beiträge
 
#1

COM: TInterfacedObject-Nachfahren explizit freigeben

  Alt 11. Okt 2002, 08:10
Hallo!

Ich möchte meinen in traditionellem OOP geschriebenen Code automatisierbar machen, deshalb bastele ich gerade daran, alle meine Objekte von o.g. Klasse abzuleiten, um den Zugriff per COM zu ermöglichen.

Dabei ergibt sich dann jedoch folgendes Problem:
Gebe ich das Objekt mit free frei, bekomme ich Zugriffschutzverletzungen; solche Objekte werden eigentlich automatisch von dieser Garbage-Collection freigegeben, sobald keine Schnittstellen-Referenzen zu diesem Objekt mehr existieren.

Eine automatische Freigabe wird aber bei meiner Objektstruktur nie erfolgen, weil ich die einzelnen Objekte sich untereinander referenzieren lasse (z.B. über eine Eigenschaft Owner).

Wie löse ich also dieses Problem? Hat jemand eine Idee?

Cu,
Udontknow
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#2
  Alt 11. Okt 2002, 10:02
Hi,

erst einmal zum Begriff "Garbage-Collection" COM unterstützt eine solche Garbage-Collection nicht in diesem Sinne. COM Objekte werden, wie Du es bereits geschrieben hast, durch Referenzzähler "am Leben" erhalten.

Wenn auf ein COM Objekt verwiesen wird, so wird bei Delphi automatisch die Methode _AddRef aufgerufen, welche den Referenzzähler um eins erhöht. Wenn der Verweis auf ein COM Objekt verfällt oder gelöscht wird, so wird die Methode _Release aufgerufen. Dadurch wird der Referenzzähler um eins verringert. Erreicht dieser 0, so wird vom Objekt die Methode Destroy aufgerufen. ("Auto-Referenced Objects")

Wenn Du jetzt Referenzen zwischen zusammenhängenden Objekten verteilen musst, dann gibt es grundlegend drei Möglichkeiten.

1. (unfein ) Das von "aussen" erstellte Objekt muss via einem Sonderaufruf (z.B. Object.AllDone) informiert werden, dass es intern all Referenzen auf von ihm erstellte Objekte freigeben soll.

2. (sehr schwer realisierbar) Du erstellst in Deinen Objekte eine Methode zum Override der Funktionen
Code:
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
; Diese müssen dann die entsprechenden Verhältnisse prüfen und gegebenenfalls Referenzen freigeben.

3. (hat auch Vor- und Nachteile) Du übergibst zwischen den erstellten Objekten nicht die COM-Schnittstellen sondern die Objekte selbst. Dadurch verlierst Du leider die Garantie, das ein referenziertes Objekt wirklich noch existiert, ausser Du kreierst eine Art "Event-Sink", an dem sich das referenzierende Objekt anmeldet, um zu erfahren, sobald das referenzierte Objekt zerstört wird.

Ich hoffe das hat geholfen.

Ciao,
......
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
Udontknow

Registriert seit: 17. Jun 2002
223 Beiträge
 
#3
  Alt 11. Okt 2002, 11:01
Hi! Danke für die schnelle Antwort!

Also,
mit Garbage-Collection meinte ich auch kein COM-Feature, sondern das Feature von Delphi, das ja, sobald eine IInterface-Variable Out-Of-Scope geht bzw. auf NIL gesetzt wird, eben die Routine _Release aufruft. Genau das ist die Problematik!

Zu 1.
Habe ich auch probiert. Alle Zeiger auf untergeordnete Objekte auf NIL setzen. So weit so gut, aber was ist, wenn die inneren Objekte sich daraufhin nicht zerstören (z.B. weil ein Client, der mein Programm automatisieren will, per COM-Schnittstelle eben noch eine Referenz auf ein untergeordnetes Objekt hat)? Dann ist zwar die Referenz vom Hauptobjekt zum Detailobjekt weg, aber das Detailobjekt schwirrt aufgrund der noch vorhandenen Referenz durch irgendein anderes unbestimmbares Client-Objekt noch immer im Speicher herum. Der Client könnte an dem Objekt Manipulationen vornehmen, ohne zu wissen, das dieses Objekt gar nicht mehr Bestandteil der eigentlichen Anwendung ist.

Zu 2.
Das ist ja der Knackpunkt, es gibt keine Möglichkeit, die Referenzen von ausserhalb zu ermitteln! Nur die Anzahl der Referenzen wird mir von TInterfaced-Object bereitgestellt. Ich habe keine Chance, sämtliche Objekte zu ermitteln, die ein Interface auf eines meiner Objekte haben.
Ich habe auch schon versucht, _Addref und _Release aussen vor zu lassen, indem ich diese Methoden übersteuere und dort nichts tue, und einfach das Objekt per Free freizugeben, aber das bewirkt dann (vermutlich aufgrund dieser Delphi-Garbage-Collection) Zugriffsschutzverletzungen direkt nach Beendigung des Destruktors.

Zu 3.
Dann ist meine Applikation aber nicht mehr automatisierbar im Sinne von COM, und das ist ja gerade das Ziel! Im Moment übergebe ich tatsächlich überall nur Objektzeiger im Sinne von TMeinObjekt, und das macht auch gar keine Schwierigkeiten, da ich eben die Gewalt über die Lebenszeit aller Objekte habe.
Aber jetzt, wo ich auf COM umstellen will, stehe ich vor einem grossen Problem. Wenn bei traditionellem OOP irgendwo Referenzen auf ein schon freigegebenes Objekt vorliegen, kommt es bei Benutzung derer zu einer Zugriffsschutzverletzung, und das wars. Bei COM allerdings kann man munter weiter mit den Objekten arbeiten, bis dann plötzlich ganz merkwürdige Fehler auftreten!

Verzwickte Situation...

Cu,
Udontknow
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#4
  Alt 11. Okt 2002, 11:16
Die dritte Variante hat für mich ohne größere Probleme funktioniert. Wir haben damit ein komplett dynamisches, mehr-dimensionales Array für VBScript erzeugt. Fast jedes Objekt zeigt (verzweigt) auf ein (oder mehr) beliebiges anderes Objekt in der Liste.
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
Udontknow

Registriert seit: 17. Jun 2002
223 Beiträge
 
#5
  Alt 11. Okt 2002, 11:29
jaja, die dritte Variante ist ja auch mein aktueller Stand meiner Anwendung. Das funktioniert. Aber es ist nun mal dann nicht durch andere Programme nutzbar.
Wie willst du denn bitte schön dem C++ Compiler die Struktur von TMeinObjekt und seiner Nachfahren mitteilen, wie willst du ihm die zur Laufzeit erstellten Objekte des Delphiprogramms übergeben? Genau dafür werden ja COM-Interfaces geschrieben, um z.B. die Kommunikation zweier Programme untereinander zu realisieren.

Ich will eben bei meinem Programm die Möglichkeit geben, auf die Ausführung durch ein beliebiges anderes Programm Einfluss zu nehmen, sodaß Drittentwickler z.B. Modifikationen meines Programmes entwickeln können.

Oder meinst du etwa, daß ich sämtliche Funktionalitäten sämtlicher Klasseninstanzen (etwa 60 verschiedene) alle in einem Steuerungsobjekt unterbringen sollte? *UFF!*
  Mit Zitat antworten Zitat
Udontknow

Registriert seit: 17. Jun 2002
223 Beiträge
 
#6
  Alt 14. Okt 2002, 08:14
Hallo,

um die Problematik mit der unkontrollierbaren Lebenszeit der Objekte in den Griff zu bekommen, habe das nun so realisiert, daß ich sämtlichen Klassen noch ein Flag Destroyed mitgebe. Bei Funktionsaufrufen in den Objekten wird dieses immer mit abgeprüft, ist Destroyed True gebe ich dann eine Exception raus...
Um das Problem der gegenseitigen Referenz aufzuheben, musste ich neben dem Einführen des Flags dann auch noch eine andere Methode DoDestroy einführen, die sämtliche Interfaces des Objekts auf NIL setzt.

@Sakura:
Evtl habe ich dich falsch verstanden. Du sagst, ihr habt eben immer nur Objekte übergeben und keine Interfaces, und seid trotzdem in der Lage, jedes einzelne Unterobjekt aus einem anderen Programm (z.B. VBScript) per COM anzusprechen? Wie das?

Cu,
Udontknow
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#7
  Alt 14. Okt 2002, 10:14
Die OPbjekte werden intern erzeugt und nur über die Interfaces nach aussen freigegeben. Dadurch kann man intern das Objekthandling nutzen und nach aussen mit den Interface-Deklarationen arbeiten.
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
Udontknow

Registriert seit: 17. Jun 2002
223 Beiträge
 
#8
  Alt 14. Okt 2002, 10:35
Wie, und ihr bekommt keine Zugriffsschutzverletzungen beim Freigeben? Bei mir scheppert, wie schon gesagt, das dann ganz gewaltig; Sobald ich noch eine Referenz auf so ein Unterobjekt habe, bekomme ich Schwierigkeiten:

Entweder:
a) eine EInvaldPointer-Exception ('Ungültige Zeiger-Operation'), direkt nachdem der Destructor ausgeführt wurde.
oder:
b) eine Zugriffsschutzverletzung, wenn das DetailObjekt unbeabsichtigt durch _release einer Client-Anwendung zerstört wird, und mein Haupt-Objekt dann das Detailobjekt per Free freigeben will

Von welcher Klasse habt ihr denn eure Objekte abgeleitet? Auch TInterfaced-Object? Habt ihr irgendetwas übersteuert?

Cu,
Udontknow
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#9
  Alt 14. Okt 2002, 10:42
Nix da mit übersteuern. Eigentlich ist alles von ersten Objekt abhängig. Sobald das "Urobjekt" freigegeben wird, werden die Refernzen auf die Unterobjekte freigegeben und "es geht los"

Das die Objekte speziell für den ASP Einsatz sind, haben wir diese direkt von TASPMTSObject <- TAutoObject <- TTypedComObject <- TComObject <- TObject abgeleitet.
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
Udontknow

Registriert seit: 17. Jun 2002
223 Beiträge
 
#10
  Alt 14. Okt 2002, 11:10
Hmmm, TCOMObject... Gut, aber das wäre ja für meine Zwecke ein wenig überdimensioniert... Ich muss ja nicht jede Klasse extern instanziieren können.
Mit wievielen Objekt-Instanzen habt ihr es denn zu tun? Bei mir kann es ganz schnell in die Zehntausende reingehen, daher sollte so eine Struktur so klein wie möglich sein.

Habt ihr denn da irgendwie mit Aggregation gearbeitet? Sprich: Ist bei euren Unterobjekten die Eigenschaft Controller<>NIL, benutzt ihr die Methode CreateAggregated, um interne Objekte zu erzeugen?

Cu,
Udontknow
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 10:30 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