Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Interface und Zugriffsverletzung (https://www.delphipraxis.net/96309-interface-und-zugriffsverletzung.html)

_frank_ 22. Jul 2007 02:04


Interface und Zugriffsverletzung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Guten morgen,

ich habe mal versucht, mich bisschen mit Interfaces zu beschäftigen, da ich meinen DFM-Editor in näherer Zukunft mit Plugins ausstatten möchte. So wie es aussieht, eigenen sich interfaces dafür am besten.
hab mir bezüglich Plugins folgendes durchgelesen:
http://www.delphipraxis.net/internal...ect.php?t=5390
hier hat aber das plugin scheinbar nicht die Möglichkeit das Hauptprogramm zu steuern, was mit interfaces möglich ist.
im folgenden Thread werden Interface-Plugins erläutert:
http://www.delphipraxis.net/internal...ect.php?t=4203
der code scheint nicht ganz vollständig zu sein. es wird auch das problem mit der Zugriffsverletzung angesprochen, jedoch die "lösung" entfernt meine AV leider nicht :?
genau sinds 2 Exceptions, eine beim freigeben der dll (scheinbar bereits freigegebenes Objekt) und eine beim beenden (nil-pointer, jedoch ist das app-objekt noch gültig). :gruebel:

ich hänge mal das komplette Test-Programm an...hoffe es kennt sich jemand etwas besser aus und kann mir sagen, warum die exceptions kommen bzw. wie man diese entfernen kann. :stupid:

Gruß Frank

hoika 22. Jul 2007 07:00

Re: Interface und Zugriffsverletzung
 
Hallo,

ohne jetzt überhaupt reinzuschauen ;)

Interfaces unter Delphi sind COM-Interfaces.
Die daranhängendenden Objekte werden "wild" freigegeben,
wenn das Interface seine Gültigkeit verliert.

Wird das Interface z.B. als lokale Variable definiert,
wird nach Beenden der Methode auch das Objekt freigegeben.
Da muss man dann Rumtricksen mit _AddRef und Release.
Deine Interfaces müssen die beiden Methoden überschreiben
und dort gar nichts tun, also keine Referenz hochzählen und Runterzählen.
Das Interface muss dann selber wieder freigegeben werden
(auf NIL setzen reicht wohl nicht).


Ich bin da auch schön reingefallen.

Ich wollte ein c# Bsp 1:1 nach Delghi übersetzen
und hatte auch AV ohne Ende.

Setze mal einen Breakpoint auf den Destructor der Klasse,
dann siehst du, was ich meine.


Heiko

_frank_ 22. Jul 2007 12:00

Re: Interface und Zugriffsverletzung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von hoika
Hallo,

ohne jetzt überhaupt reinzuschauen ;)

Interfaces unter Delphi sind COM-Interfaces.
Die daranhängendenden Objekte werden "wild" freigegeben,
wenn das Interface seine Gültigkeit verliert.

na super :drunken:
Zitat:

Zitat von hoika
Wird das Interface z.B. als lokale Variable definiert,
wird nach Beenden der Methode auch das Objekt freigegeben.
Da muss man dann Rumtricksen mit _AddRef und Release.
Deine Interfaces müssen die beiden Methoden überschreiben
und dort gar nichts tun, also keine Referenz hochzählen und Runterzählen.
Das Interface muss dann selber wieder freigegeben werden
(auf NIL setzen reicht wohl nicht).

mhm...hab das mal probiert, habe zwar die nil-Pointer-exception nicht mehr, aber die bei freigeben der dll bleibt :gruebel:
und wie geb ich das interface dann frei? free gibts ja nicht...
Zitat:

Zitat von hoika
Setze mal einen Breakpoint auf den Destructor der Klasse,
dann siehst du, was ich meine.

ehrlich gesagt, ich seh nichts :roll:

Gruß Frank

hoika 22. Jul 2007 12:39

Re: Interface und Zugriffsverletzung
 
Hallo,

> ich seh nix

beim Verlassen des Gültigkeitsbereiches eines
Interfaces wird nicht nur das Interface "gelöscht",
sondern auch das betroffene Objekt gelöscht.

Abhilfe bringt nur _AddRef und Release zu überschreiben
und dort nichts tun (Referenzzählung deaktivieren).

Ein Interface wird normalerweise freigegeben,
wenn es auf NIL gesetzt wird.

Probier mal mit memcheck, ob das reicht.


Ich hatte nach dem einen Test so die "Schnauze voll",
dass ich erst wieder was mit machen werden,
wenn delphi.net bei uns ansteht.


Heiko

_frank_ 22. Jul 2007 13:24

Re: Interface und Zugriffsverletzung
 
Zitat:

Zitat von hoika
Hallo,

> ich seh nix

beim Verlassen des Gültigkeitsbereiches eines
Interfaces wird nicht nur das Interface "gelöscht",
sondern auch das betroffene Objekt gelöscht.

Abhilfe bringt nur _AddRef und Release zu überschreiben
und dort nichts tun (Referenzzählung deaktivieren).

das hab ich ja gemacht...
Delphi-Quellcode:
//anwendungsseite
function TApp._AddRef: Integer; stdcall;
begin
  //
end;

function TApp._Release: Integer; stdcall;
begin
  //
end;

function TMemoWrapper._AddRef: Integer;
begin
  //
end;

function TMemoWrapper._release: Integer;
begin
  //
end;

//plugin-seite
function TPlugin._AddRef: Integer;
begin
  //
end;

function TPlugin._release: Integer;
begin
  //
end;
die variable app:TApp ist im Gültigkeitsbereich der form, ist auch im destroy des forms korrekt gesetzt (inkl. Interface auf Ieditor), wo es dann freigegeben wird. Es kommt auch keine nil-pointer exception beim beenden mehr...

muss ich vor dem freigeben der dll das TPlugin-Objekt irgendwie freigeben, oder reicht das per nil-Zuweisung beim Interface anwendungsseitig? (habs zumindest nicht ohne AV hinbekommen)

Zitat:

Zitat von hoika
Ein Interface wird normalerweise freigegeben,
wenn es auf NIL gesetzt wird.

Probier mal mit memcheck, ob das reicht.

Ich hatte nach dem einen Test so die "Schnauze voll",
dass ich erst wieder was mit machen werden,
wenn delphi.net bei uns ansteht.

vielleicht findet ja auch jemand anderes Lust, der sich auskennt :)
gibt sicher ne ganz triviale lösung...so umfangreich ist es ja (noch) nicht...kanns nur nicht richtig nachvollziehen, warum die AV kommt. Muss man evtl irgendwas festes bei den beiden funktionen zurückgeben? weil so sind die ja undefiniert...

Gruß Frank

xaromz 22. Jul 2007 14:05

Re: Interface und Zugriffsverletzung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

mit _AddRef und _Release würde ich erst experimentieren, wenn ich mich gut mit Interfaces auskenne.
Ich habe Dein Beispiel aus dem ersten Beitrag mal etwas überarbeitet und folgende Änderungen vorgenommen:
  • Instanzen und Interfaces nicht mehr gemischt (IApp/TApp). Diese niemals mischen (siehe oben: man sollte genau wissen, was man tut)
  • Interfaces werden per const übergeben (dadurch wird die Referenzzählung nicht belastet)
  • DLL wird beim Programmstart geladen und beim Beenden entladen
  • IApp ist von Form1 entkoppelt
Du solltest nie eine DLL entladen, wenn Du in der Methode ein lokales Interface dieser DLL hast. Beim Beenden der Funktion sorgt die Compiler-Magic nämlich dafür, dass das Interface abgebaut wird. Wenn aber die DLL bereits entladen ist, dann gibt's eine AV.

Gruß
xaromz

_frank_ 22. Jul 2007 15:07

Re: Interface und Zugriffsverletzung
 
Zitat:

Zitat von xaromz
Hallo,

Hallo, und danke dir erstmal, funktioniert schonmal super :)
Zitat:

Zitat von xaromz
mit _AddRef und _Release würde ich erst experimentieren, wenn ich mich gut mit Interfaces auskenne.

naja, kenn ich ja noch net aus damit, und hab ich ja auch nur, um die AVs wegzubekommen :)
Zitat:

Zitat von xaromz
Ich habe Dein Beispiel aus dem ersten Beitrag mal etwas überarbeitet und folgende Änderungen vorgenommen:
  • Instanzen und Interfaces nicht mehr gemischt (IApp/TApp). Diese niemals mischen (siehe oben: man sollte genau wissen, was man tut)
  • Interfaces werden per const übergeben (dadurch wird die Referenzzählung nicht belastet)
  • DLL wird beim Programmstart geladen und beim Beenden entladen
  • IApp ist von Form1 entkoppelt

das mit dem mischen hab ich noch nicht ganz verstanden...du übergibst doch auch ein interface an die klasse TApp beim create (bzw. wird das memo-Objekt als Interface weitergegeben). TMemoWrapper wird wohl selbst auch als Interface interpretiert bzw. gibt dessen contructor das Interface zurück, was in der deklaration (class(TInterfacedObject, IEditor)) angegeben wurde?

zu dem entkoppeln...muss ich mal schauen, wie ich das dann mache wenn ich zugriff auf mehrere Objekte brauche, momentan ists ja zum test nur das memo...
Zitat:

Zitat von xaromz
Du solltest nie eine DLL entladen, wenn Du in der Methode ein lokales Interface dieser DLL hast. Beim Beenden der Funktion sorgt die Compiler-Magic nämlich dafür, dass das Interface abgebaut wird. Wenn aber die DLL bereits entladen ist, dann gibt's eine AV.

und bei globalen/"form-gültigen" interface-Typen ist das nicht so? versteh ich nicht so ganz...naja Compiler-Magic :)

hab zumindest erstmal einen funktionierenden startpunkt und paar Infos, den rest muss ich ausprobieren bzw. schauen, was ich so dazu finde :)
werde mir den Source so nochmal in einer Ruhigen minute zu Gemüte führen, habs jetzt nur überflogen und die änderungen gesucht bzw. deine Punkte daran nachvollzogen (zumindest versucht) :)

wird eh erst eingebaut, wenn (endlich mal) die Background-Klasse für den DFM-Editor fertig ist und eingebaut ist...ist auch massig Arbeit, das alles anzupassen. wollte das nur im vorfeld schonmal bisschen probieren. Dem Interface wird dann diese Background-Klasse übergeben, welche sich per Event um das Treeview kümmert und das Plugin rührt dann nicht in der vcl (wenn auch indirekt) rum... maximal bei Menüeinträgen, aber da muss aich auch schauen, wie ich das mit der toolbar (besonders den Glyphs) mache.

Gruß Frank

xaromz 22. Jul 2007 16:19

Re: Interface und Zugriffsverletzung
 
Hallo,

was das Mischen von Instanzen und Interfaces angeht kann ich Dich an meine Einführung in Interfaces verweisen.

Gruß
xaromz

Bernhard Geyer 22. Jul 2007 16:46

Re: Interface und Zugriffsverletzung
 
Zitat:

Zitat von hoika
Interfaces unter Delphi sind COM-Interfaces.
Die daranhängendenden Objekte werden "wild" freigegeben,
wenn das Interface seine Gültigkeit verliert.

Das kann ich so nicht stehen lassen:

1, Interfaces unter Delphi sind an COM angelehnt, aber funktionieren wunderprächtig auch Delphi-Intern und auch unter Linux (Kylix)
2, Sie werden (im Gegensatz zu .NET) nicht "wild" freigegeben (die "dahinterliegende" Instanz eines Objekts) sondern sofort wenn es keinen Interfacezeiger mehr darauf gibt (Referenzzählung). Nur wenn man den Tipp von xaromz (Keine Mischverwendung Instanzen und Interfaces) nicht berücksichtigt bekommst man Probleme mit der Delphi-Implementierung von Interfaces).

Zitat:

Zitat von hoika
Wird das Interface z.B. als lokale Variable definiert,
wird nach Beenden der Methode auch das Objekt freigegeben.
Da muss man dann Rumtricksen mit _AddRef und Release.

Und wieso das? Wenn die Variable/Interface lokal ist dann sollte sie doch freigeben werden nach dem Verlassen. Du hast ja auch keine Variable mehr um darauf zuzugreifen.

Wenn man 2-3 Fallen der Delphi-Implementierung umschifft dann sind Interfaces in Delphi (im Gegensatz z.B. zu C/C++, auch mit Smartpointer) easy zu verwenden und auch sehr Pflegeleicht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:22 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