AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Memory Leak bei Interface Delegation

Ein Thema von dpg123 · begonnen am 27. Okt 2016 · letzter Beitrag vom 26. Jul 2019
Antwort Antwort
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Memory Leak bei Interface Delegation

  Alt 27. Okt 2016, 10:50
Hier noch ein paar Infos:

AggregatedObject


Stackoverflow


Delphi-Quellcode:
unit Unit1;

interface

type
  IMyInterface = interface
    procedure ShowInfo;
  end;

  // Ableiten von TAggregatedObject
  TMyClass = class(TAggregatedObject, IMyInterface)
    procedure ShowInfo;
  end;


  TMyWrapper = class(TInterfacedObject, IMyInterface)
   private
     // Wir "besitzen" also die Klasse selber speichern

     FMyClass: TMyClass;
    function getMyInterface: IMyInterface;

   public
    constructor Create;
    destructor Destroy; override;
    property MyInterface: IMyInterface read getMyInterface implements IMyInterface;
  end;

  procedure Test;
implementation

uses
  System.SysUtils;




procedure TMyClass.ShowInfo;
begin
  writeln('Call ShowInfo');
end;

constructor TMyWrapper.Create;
begin
  inherited;
  FMyClass := TMyClass.Create(self);
end;

destructor TMyWrapper.Destroy;
begin
  inherited;
  // Klasse freigeben
  FMyClass.Free;
end;

function TMyWrapper.getMyInterface: IMyInterface;
begin
  result := FMyClass as IMyInterface;
end;

procedure Test;
  var MyInterface: IMyInterface;
begin
  MyInterface := TMyWrapper.Create(); // <- mit dieser Zeile Memory Leak
  MyInterface.ShowInfo;

// Kein Leak :-)



end;


end.
Fritz Westermann
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Memory Leak bei Interface Delegation

  Alt 27. Okt 2016, 11:16
[F1] auf Delphi-Referenz durchsuchenimplements nennt zuerst die Variante mit dem Interface als Property und danach eine mit der Klasse.

Woebei die Klasse da nichtmal ein Interface ist, laut dem gezeigten Beispiel.
http://docwiki.embarcadero.com/RADSt..._Typ_Interface
Die OH verwendet auch nirgendwo einen Getter, der auf dem Object ein Interface macht, beim Zugrif.

Und nach meinem Verständnis sollte man eigentlich eh niemals Interface-Referenzen mit Objekt-Referenzen auf das selbe Objekt mischen?
(Ausnahme die TComponents, welche nicht referenzgezählt sind, auch wenn das schon ein bissl krank ist, denn das knallt, wenn man ein Free macht, bevor die letzte Interfacereferenz freigegeben wurde)

Beides vom Typ Interface und ich hab diesmal zwei Speicherlecks. (TInterfacedObject statt TAggregatedObject ergab nur ein Speicherleck )
Delphi-Quellcode:
type
  IMyInterface = interface
    procedure Show;
  end;

  TMyClass = class(TAggregatedObject, IMyInterface)
    procedure Show;
  end;

  TMyWrapper = class(TInterfacedObject, IMyInterface)
  private
    FMyInterface: IMyInterface;
  public
    constructor Create;
    property MyInterface: IMyInterface read FMyInterface implements IMyInterface;
  end;

procedure TMyClass.Show;
begin
  ShowMessage('blubb');
end;

constructor TMyWrapper.Create;
begin
  inherited;
  FMyInterface := TMyClass.Create(Self);
end;

procedure TForm4.FormCreate(Sender: TObject);
var
  MyInterface: IMyInterface;
begin
  ReportMemoryLeaksOnShutdown := True;
  MyInterface := TMyWrapper.Create;
  MyInterface.Show;
end;
Mit der Klasse als interface hab ich kein Speicherleck.
Delphi-Quellcode:
type
  IMyInterface = interface
    procedure Show;
  end;

  TMyClass = class(TAggregatedObject, IMyInterface)
    procedure Show;
  end;

  TMyWrapper = class(TInterfacedObject, IMyInterface)
  private
    FMyClass: TMyClass;
  public
    constructor Create;
    destructor Destroy; override;
    property MyInterface: TMyClass read FMyClass implements IMyInterface;
  end;

procedure TMyClass.Show;
begin
  ShowMessage('blubb');
end;

constructor TMyWrapper.Create;
begin
  inherited;
  FMyClass := TMyClass.Create(Self);
end;

destructor TMyWrapper.Destroy;
begin
  FMyClass.Free;
  inherited;
end;

procedure TForm4.FormCreate(Sender: TObject);
var
  MyInterface: IMyInterface;
begin
  ReportMemoryLeaksOnShutdown := True;
  MyInterface := TMyWrapper.Create;
  MyInterface.Show;
end;
Die Klasse als Klasse funktioniert auch.
Delphi-Quellcode:
type
  IMyInterface = interface
    procedure Show;
  end;

  TMyClass = class
    procedure Show;
  end;

  TMyWrapper = class(TInterfacedObject, IMyInterface)
  private
    FMyClass: TMyClass;
  public
    constructor Create;
    destructor Destroy; override;
    property MyInterface: TMyClass read FMyClass implements IMyInterface;
  end;

procedure TMyClass.Show;
begin
  ShowMessage('blubb');
end;

constructor TMyWrapper.Create;
begin
  inherited;
  FMyClass := TMyClass.Create;
end;

destructor TMyWrapper.Destroy;
begin
  FMyClass.Free;
  inherited;
end;

procedure TForm4.FormCreate(Sender: TObject);
var
  MyInterface: IMyInterface;
begin
  ReportMemoryLeaksOnShutdown := True;
  MyInterface := TMyWrapper.Create;
  MyInterface.Show;
end;
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (27. Okt 2016 um 11:21 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke
Online

Registriert seit: 10. Jun 2003
Ort: Berlin
9.962 Beiträge
 
Delphi 12 Athens
 
#3

AW: Memory Leak bei Interface Delegation

  Alt 27. Okt 2016, 11:55
(Ausnahme die TComponents, welche nicht referenzgezählt sind, auch wenn das schon ein bissl krank ist, denn das knallt, wenn man ein Free macht, bevor die letzte Interfacereferenz freigegeben wurde)
Deshalb sollte man auch möglichst keine Interfaces auf TComponent-Nachkommen selbst nutzen. Wir haben z.B. ein GUI-Interface, das durch eine separate Klasse implementiert wird, die die visuelle Komponente lediglich kennt. Wird diese freigegeben, entfernt sie die Referenz, aber das separate Objekt bleibt bestehen. (Und leitet Zugriffe schlicht nicht mehr weiter.)
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.652 Beiträge
 
Delphi 12 Athens
 
#4

AW: Memory Leak bei Interface Delegation

  Alt 27. Okt 2016, 23:06
Woebei die Klasse da nichtmal ein Interface ist, laut dem gezeigten Beispiel.
Weil die Klasse das Interface zwar implementieren, aber es nicht auch noch unterstützen muss.

Das implements ist sogar noch flexibler:
Die Klasse, die bei dem implements steht, muss gar nicht das gesamte Interface implementieren. Es genügt, wenn die fehlenden Methoden von der Wrapper-Klasse implementiert werden.

Delphi-Quellcode:
type
  IMyInterface = interface
    procedure Foo;
    procedure Bar;
  end;

  TMyClass = class
  protected
    procedure Foo;
  end;

  TMySuperClass = class(TInterfacedObject, IMyInterface)
  private
    FMyClass: TMyClass;
    function GetMyClass: TMyClass;
  protected
    procedure Bar;
    property MyClass: TMyClass read GetMyClass implements IMyInterface;
  public
    destructor Destroy; override;
  end;
Das geht sogar noch weiter: Sollten beide Klassen eine Methode des Interfaces implementieren, dann hat die Implementation der Wrapper-Klasse Vorrang.

Delphi-Quellcode:
type
  IMyInterface = interface
    procedure Foo;
    procedure Bar;
  end;

  TMyClass = class
  protected
    procedure Foo;
    procedure Bar;
  end;

  TMySuperClass = class(TInterfacedObject, IMyInterface)
  private
    FMyClass: TMyClass;
    function GetMyClass: TMyClass;
  protected
    procedure Bar; // hat Vorrang for MyClass.Bar
    property MyClass: TMyClass read GetMyClass implements IMyInterface;
  public
    destructor Destroy; override;
  end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Memory Leak bei Interface Delegation

  Alt 28. Okt 2016, 08:20
Zitat:
Das geht sogar noch weiter: Sollten beide Klassen eine Methode des Interfaces implementieren, dann hat die Implementation der Wrapper-Klasse Vorrang.

Delphi-Quellcode:
type
  IMyInterface = interface
    procedure Foo;
    procedure Bar;
  end;

  TMyClass = class
  protected
    procedure Foo;
    procedure Bar;
  end;

  TMySuperClass = class(TInterfacedObject, IMyInterface)
  private
    FMyClass: TMyClass;
    function GetMyClass: TMyClass;
  protected
    procedure Bar; // hat Vorrang for MyClass.Bar
    property MyClass: TMyClass read GetMyClass implements IMyInterface;
  public
    destructor Destroy; override;
  end;
Ja das ist schon interessant, aber in meinen Augen auch nicht sehr übersichtlich. Versuch das mal einem nicht Delphianer beizubringen.
Wenn das property auch als interface deklariert wird gewinnt das property...
Muss man wissen oder leidvoll erfahren.
Fritz Westermann
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Memory Leak bei Interface Delegation

  Alt 28. Okt 2016, 09:50
Und wer gewinnst, wenn man mehrere Klassen delegiert?
Bestimmt der mit dein meisten Bytes im Code, wo mindstens ein Byte den Wert 666 hat.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.490 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Memory Leak bei Interface Delegation

  Alt 26. Jul 2019, 14:01
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Das passt ja genau hierher
  Mit Zitat antworten Zitat
dpg123

Registriert seit: 13. Apr 2015
22 Beiträge
 
Turbo Delphi für Win32
 
#8

AW: Memory Leak bei Interface Delegation

  Alt 4. Nov 2016, 14:44
Entschuldigt die späte Rückmeldung!

Ich muss noch mal nachfragen: sehe ich es richtig, dass es mit folgender Deklaration

Delphi-Quellcode:
type
  IMyInterface = interface
    procedure Show;
  end;

  TMyClass = class(TAggregatedObject, IMyInterface)
    procedure Show;
  end;

  TMyWrapper = class(TInterfacedObject, IMyInterface)
  private
    FMyInterface: IMyInterface;
  public
    constructor Create;
    property MyInterface: IMyInterface read FMyInterface implements IMyInterface;
  end;
keine sauber Implementation ohne manuelles Freigeben von FMyInterface gibt? Und wie sähe diese mit Freigeben aus?

Dank und Gruß!

Geändert von dpg123 ( 4. Nov 2016 um 14:47 Uhr)
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.199 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: Memory Leak bei Interface Delegation

  Alt 25. Jul 2019, 18:51
Ich bin grade selber hierrüber gestoplert. Man braucht echt eine Weile bis man die Ursache gefunden hat. Soweit ich es sehe gibt es tatsächlich keine wirkliche Lösung für das Speicherleck. Bei der Zuweisung in die Variable zeigt er direkt auf das innere Objekt. Das implements-Schlüsselwort sollte einen zwingen an TContainedObject oder TAggregatedObject zu delegieren. Oder zumindest eine Warnung ausspucken.

Fazit: Ich streiche implements aus meinem Vokabular. Die paar Zeilen Tipparbeit für explizite Delegation an eine Instanz sind sowieso übersichtlicher.
  Mit Zitat antworten Zitat
Antwort Antwort

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 18:02 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