AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi RefCount nach Erstellung von TInterfacedObject gleich 0
Thema durchsuchen
Ansicht
Themen-Optionen

RefCount nach Erstellung von TInterfacedObject gleich 0

Ein Thema von s.h.a.r.k · begonnen am 13. Jan 2012 · letzter Beitrag vom 13. Jan 2012
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#1

RefCount nach Erstellung von TInterfacedObject gleich 0

  Alt 13. Jan 2012, 14:12
Delphi-Version: XE2
Hallo zusammen,

ich habe gerade ein irgendwie unschönes Problem mit Interfaces. Gehe um Moment immer mehr dazu über Interfaces zu verwenden, da es an einigen Stellen echt praktisch sein kann. Dann gibt es aber immer wieder merkwürdige Dinge, die ich (noch) nicht so recht verstehe... Und zwar geht um im Moment um den folgenden Code -- ja, der ist leicht anders als der auf dem Bild im Anhang!
Delphi-Quellcode:
TBaseStartupProcess = class(TInterfacedObject, IStartupProcess, IStartupProcessCommandContainer)
end;

class function TStartupManagerFactory.Create(): IStartupProcess;
var
  StartupProcess : TBaseStartupProcess;
begin
  StartupProcess := TBaseStartupProcess.Create();
  AddStartupCommands(StartupProcess);
  Result := StartupProcess;
end;
Ich finde, dass da ja nichts besonderes dran ist. Mit der lokalen Variablen muss ich arbeiten, da die AddStartupCommands einen Parameter vom Typ TBaseStartupProcess erwartet -- das Interface kann ich hier nicht nutzen, da ich in der AddStartupCommands Dinge mit dem Objekt mache, die nicht vom Interface abgedeckt sind.

Jedenfallst ist es so, dass wenn ich obigen Code verwende, direkt nach der AddStartupCommands-Methode, die Destroy-Methode von StartupProcess aufgerufen wird. Habe das dann weiter verfolgt und bin darauf gestoßen, dass direkt nach dem Erzeugen des Objekts RefCount gleich 0 ist. Hier die Frage: wie kann sowas sein? StartupProcess zeigt doch auf das neu erzeugte Objekt, ergo müsste doch RefCount gleich 1 sein -- im Screenshot könnt ihr das auch nochmals sehen.

Wenn ich den Code umstelle, wie im Screenshot gezeigt, so ist alles in Butter und die Destroy-Methode wird nach dem Aufruf von AddStartupCommands nicht aufgerufen, da RefCount nach der Zuweisung Result := StartupProcess; 1 ist, und nicht 0.

Ich hoffe, dass hier jemand Licht ins Dunkel bringen kann!
Angehängte Grafiken
Dateityp: png interface-refcount.png (16,7 KB, 16x aufgerufen)
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: RefCount nach Erstellung von TInterfacedObject gleich 0

  Alt 13. Jan 2012, 15:05
Die Referenzzählung erfolgt IMHO erst dann, wenn die Instanz zu einer Interface-Variablen zugeordnet wird.

Probier es mal so
Delphi-Quellcode:
class function TStartupManagerFactory.Create(): IStartupProcess;
var
  StartupProcess : TBaseStartupProcess;
begin
  StartupProcess := TBaseStartupProcess.Create();
  Result := StartupProcess;
  AddStartupCommands(StartupProcess); // Hier mal den Haltepunkt setzen und prüfen
end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: RefCount nach Erstellung von TInterfacedObject gleich 0

  Alt 13. Jan 2012, 16:11
So solte das doch eigentlich funktionieren
Delphi-Quellcode:
class function TStartupManagerFactory.Create(): IStartupProcess;
begin
  Result := TBaseStartupProcess.Create();
  AddStartupCommands( TBaseStartupProcess( Result ) );
end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.343 Beiträge
 
Delphi 12 Athens
 
#4

AW: RefCount nach Erstellung von TInterfacedObject gleich 0

  Alt 13. Jan 2012, 16:48
So solte das doch eigentlich funktionieren
Wenn hier nicht zufällig ein bissl Compilermagic mitspielt, dann definitiv NEIN.

Ein Interface-Zeiger ist kein Objekt-Zeiger, also kann man das nicht einfach so billig umcasten.

Zitat von mjustin:
Natürlich, aber irgendwo muss halt doch eine implementierende Klasse instanziiert werden.
Wo kann etwas schiefgehen, wenn man wie im Beispiel der Factoryklasse, die erzeugte Instanz temporär in einer lokalen Variable speichert?
Möglichst direkt in die Interfacevariable reinerstellen.

Sobald man auch nur eine Interfacevariable erstellt ht, ist die Zuferlässigkeit von Objektzeigern nicht mehr gegeben, da das Objekt vorzeitig/ungewollt über die Interface-Referenzzählung freigegeben werden könnte.

Aus diesem Grund hatte ich vor eine Weile angefangen eine Hybride zu erstellen, welche die Interfacereferenzen und Objektreferenzen gleichermaßen beachtet.
Leider ist das in Delphi (speziell die Erstellung des Objektes) nicht komplett und sicher umsetzbar,
da man nicht automatisch erkennen kann, ob das erstellte Objekt, bei x := TIrgendwas.Create; direkt in eine Interfacevariable geht oder ob das eine Objektvariable ist. (also um was es sich beim X handelt)
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (13. Jan 2012 um 16:55 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: RefCount nach Erstellung von TInterfacedObject gleich 0

  Alt 13. Jan 2012, 16:59
So solte das doch eigentlich funktionieren
Wenn hier nicht zufällig ein bissl Compilermagic mitspielt, dann definitiv NEIN.

Ein Interface-Zeiger ist kein Objekt-Zeiger, also kann man das nicht einfach so billig umcasten.
Oh, dann habe ich wohl das Hummel-Syndrom ... denn das wusste ich nicht.
Aus diesem Grunde mache ich das so ... und es funktioniert

Also, das sollte nicht nur, sondern das Casten funktioniert genau so.

Eine Hummel kann eigentlich gar nicht fliegen, da die Flügel viel zu klein für ihr Gewicht sind.
Da die Hummel das nicht weißt, fliegt sie einfach.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.343 Beiträge
 
Delphi 12 Athens
 
#6

AW: RefCount nach Erstellung von TInterfacedObject gleich 0

  Alt 13. Jan 2012, 17:06
Dann ist das ein Problem der versteckten Compilermagic.
Wenn der Compiler diesen Cast intern in eine Supports-Anfrage ändert, dann geht das natürlich.


Schade, daß man nicht sieht, ob/wo die Compilermagic einem einen "Streich" speielt.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#7

AW: RefCount nach Erstellung von TInterfacedObject gleich 0

  Alt 13. Jan 2012, 21:57
Die Referenzzählung erfolgt IMHO erst dann, wenn die Instanz zu einer Interface-Variablen zugeordnet wird.

Probier es mal so
Delphi-Quellcode:
class function TStartupManagerFactory.Create(): IStartupProcess;
var
  StartupProcess : TBaseStartupProcess;
begin
  StartupProcess := TBaseStartupProcess.Create();
  Result := StartupProcess;
  AddStartupCommands(StartupProcess); // Hier mal den Haltepunkt setzen und prüfen
end;
Jup, das hatte ich schon -- siehe den Screenshot

Die Information, dass diese Interface-Zeiger besondere Zeiger sind, wusste ich bisher (leider) noch nicht. Das ändert natürlich die Sachlage etwas danke an euch alle, vor allem die gesamte Diskussion drum herum!
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.343 Beiträge
 
Delphi 12 Athens
 
#8

AW: RefCount nach Erstellung von TInterfacedObject gleich 0

  Alt 13. Jan 2012, 22:19
Die Information, dass diese Interface-Zeiger besondere Zeiger sind, wusste ich bisher (leider) noch nicht.
Das ist grade der Sinn von Interfaces. (also einer davon)

Erstmal Trennung von Schnittstelle und Code.
> Man muß nur die Schnittstelle (die Interfacedeklaration) kennen und es ist unwichtig, was sich dahinter versteckt. (bzw. man muß nicht das Innere verraten)

Und die Freigabe regelt das Interface selber.
> Es zählt wie oft es verwendet wird (wieviele Variablen auf es zeigen) und wenn keiner mehr drauf zeigt, gibt es sich selber frei.
> Bei wird die Freigabe extern geregelt ... irgendwer ruft Free auf (wobei es nicht beachtet wird, ob noch eine andere Variable drauf zeigen könnte ... btw. niemand weiß wie oft was verlinkt wird)
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
ASM

Registriert seit: 15. Aug 2004
165 Beiträge
 
Delphi 7 Enterprise
 
#9

AW: RefCount nach Erstellung von TInterfacedObject gleich 0

  Alt 13. Jan 2012, 15:06
... bin darauf gestoßen, dass direkt nach dem Erzeugen des Objekts RefCount gleich 0 ist. Hier die Frage: wie kann sowas sein? StartupProcess zeigt doch auf das neu erzeugte Objekt, ergo müsste doch RefCount gleich 1 sein...

Ich hoffe, dass hier jemand Licht ins Dunkel bringen kann!

Möglicherweise hiermit:
Die Erklärung dazu könnte durch ein Problem verursacht sein, das detailliert hier beschrieben worden ist:
Kosch, Andreas: "COM/DCOM/COM+ mit Delphi" (ISBN 3-935042-01-9), p.92-94.

Kurz zusammengefasst: Es liegt womöglich an der Verwendung der "normalen" Delphi-Variablen StartupProcess: TBaseStartupProcess für den Zugriff auf das interfaced Objekt innerhalb der function TStartupManagerFactory.Create() anstatt, wie es richtiger wäre, der Verwendung unmittelbar einer echten Interface-Variablen (StartupProcess : IDingsbums) für das COM-Objekt. Details siehe genannte Referenz.
Von Kosch vorgeschlagener Workaround: den Verwendungszähler des COM-Objekts manuell durch Aufruf von _Addref um 1 hochzählen.
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.487 Beiträge
 
Delphi 12 Athens
 
#10

AW: RefCount nach Erstellung von TInterfacedObject gleich 0

  Alt 13. Jan 2012, 15:11
RefCount sagt nicht aus wie oft das Objekt verwendet wird, sondern wie viele Interface-Variablen existieren, die auf dieses Objekt verweisen. Deshalb ist RefCount nach dem Erzeugen erst einmal 0. Das Objekt wird nur automatisch freigegeben, wenn RefCount von 1 auf 0 fällt.

Arbeitet AddStartupCommands() durchgehend nur mit dem Objekt, so ist alles in Ordnung.
Aber vermutlich wird das Objekt dort auch einer Interfacevariable zugewiesen, die nur temporär existiert. Dadurch steigt RefCount und fällt wieder auf 0, mit dem bekannten Ergebnis.

Zitat:
Mit der lokalen Variablen muss ich arbeiten, da die AddStartupCommands einen Parameter vom Typ TBaseStartupProcess erwartet -- das Interface kann ich hier nicht nutzen, da ich in der AddStartupCommands Dinge mit dem Objekt mache, die nicht vom Interface abgedeckt sind.
Gegen die lokale Variable ist im Prinzip nichts einzuwenden, wenn diese für die Initialisierung des Objektes notwendig ist. Sobald aber ein Interface erzeugt ist, sollte man nur noch damit arbeiten. Wenn AddStartupCommands Dinge von dem Objekt erwartet, die durch die vorhandenen Interfaces nicht abgedeckt werden, so könnte man einfach ein weiteres Interface hinzufügen.

Die Variante von Sir Rufo funktioniert auch.
Allerdings sollte man solche Kniffe ausführlich kommentieren.
Sonst wundert man sich, wenn man an dieser Stelle z.B. in zwei Jahren nur eine Kleinigkeit ändert, warum nichts mehr geht...
  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 17:24 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz