AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Zugriffverletzung beim Verwenden von Interfaces
Thema durchsuchen
Ansicht
Themen-Optionen

Zugriffverletzung beim Verwenden von Interfaces

Ein Thema von mirage228 · begonnen am 14. Dez 2003 · letzter Beitrag vom 16. Dez 2003
Antwort Antwort
choose

Registriert seit: 2. Nov 2003
Ort: Bei Kiel, SH
729 Beiträge
 
Delphi 2006 Architect
 
#1

Re: Zugriffverletzung beim Verwenden von Interfaces

  Alt 15. Dez 2003, 00:04
Hallo mirage228,

wenn ich Deine Ausführungen richtig verstanden habe, liegt die Ursache des Problems in der heterogenen Verwendung von Klassen(-Objekten) und (Objekt-)Interfaces.
Bedingt durch das in Delphi verwendete Interface-Konzept wird bei der Arbeit mit Interfaces eine implizite Referenzzählung vorgenommen.

Der folgende Code
Delphi-Quellcode:
var
  myObject: IMyInterface
begin
  myObject:= GetAnObject;
  myObject.AMethod;
  myObject:= GetAnotherObject;
  myObject.AnotherMethod;
end;
wird deshalb vom Compiler um Code ergänzt, den man etwa so schreiben könnte
Delphi-Quellcode:
begin
  myObject:= GetAnObject;
  myObject._AddRef;
  myObject.AMethod;
  myObject._Release;
  myObject:= GetAnotherObject
  myObject._AddRef;
  myObject.AnotherObject;
  myObject._Release;
end;
Tatsächlich variiert der Aufruf von _Release ein wenig, so dass in diesem Beispiel die Methode erst nach dem Aufruf von GetAnotherObject aufgerufen wird, darüber hinaus sollte man sich die Referenzzählung von try..finally-Blöcken umschlossen vorstellen, der Einfachheit halber habe ich das aber vernachlässigt.

Betrachtet man nun die Implementierung von _Release in dem von Dir verwendeten Vorfahren TInterfacedObject:
Delphi-Quellcode:
function TInterfacedObject._Release: Integer;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then
    Destroy;
end;
Erkennt man, dass Objekte dieses Typs freigegeben werden, sobald der Referenzzähler null erreicht hat. Weil ein solches Objekt nach dem Verlassen des Konstruktors mit null belegt ist führt dieser Code
Delphi-Quellcode:
var
  myClassicalObject: TInterfacedObject;
  myInterfacedObject: IInterface;
begin
  myClassicalObject:= TInterfacedObject.Create;
  myInterfacedObject:= myClassicalObject; // implicit call of _AddRef
  myInterfacedObject:= nil; // implicit call of _Release -> Free;

  // !myClassicalObject contains an invalid reference, now
  Showmessage(IntToStr(myClassicalObject.RefCount));
end;
zu Problemen (dass der Code fehlerfrei funktionieren kann, liegt an der Speicherverwaltung von Delphi, führt aber spätestens bei mehreren parallelen Verarbeitungssträngen zu Problemen).

Wenn Du Dich mit diesem Phänomen eingehender beschäftigen möchtest, empfehle ich Dir, eine Testklasse zu implementieren, die die Methoden _AddRef und _Release sowie den Aufruf des Destruktors protokolliert, bzw den Code im integrierten Debugger mit Debug-DCUs und einem Nachfahren von TInterfacedObject mit Breakpoints in den entsprechenden Zeilen der Unit System zu analysieren.

Lösen lassen sollte sich das Problem relativ einfach, indem Du entweder ausschließlich "klassische Objekte" oder Interfaces verwendest. Listen für den letzteren Fall lassen sich dann zB mithilfe von TInterfaceList realisieren...
gruß, choose
  Mit Zitat antworten Zitat
Antwort Antwort


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 08:28 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