Einzelnen Beitrag anzeigen

AndyDF

Registriert seit: 6. Sep 2006
Ort: Allgäu
99 Beiträge
 
Delphi 10.4 Sydney
 
#1

Freigabe von übergebenen Interface-Instanzen

  Alt 30. Sep 2016, 10:12
Delphi-Version: 10 Seattle
Habe gerade etwas fest gestellt, von dem ich bisher erwartet hatte, dass es funktioniert. Ich arbeite sehr intensiv mit Interfaces und schaue auch immer, dass ich Objekt- und Interfacereferenzen nicht vermische.
Das heißt, Variable vom Interface-Typ definierten und das Objekt mittels Create der Variable zuweisen. Wenn die Interface-Variable aus dem Scope fällt, wird das Objekt dahinter auch immer schön frei gegeben. So soll das sein!

Jetzt hätte ich erwartet, wenn eine Methode eine Interface-Variable übernimmt, und ich beim Aufruf direkt die neu erstelle Objekt-Referenz übergebe, dass der RefCount und die Freigabe korrekt funktionieren. Dem ist anscheinend nicht so. Im Folgenden mal ein Beispiel-Code. Habe an der entsprechenden Stelle einen Kommentar eingefügt...


Delphi-Quellcode:
type
  IMyInterface = interface(IInterface)
    ['{475ACE39-ECC7-467D-A325-35B2DF22203A}']
    procedure DoSomething;
  end;

  TMyInterface = class(TInterfacedObject, IMyInterface)
  private
    procedure DoSomething;
  public
    destructor Destroy; override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure Machwas(const AValue: IMyInterface);
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

destructor TMyInterface.Destroy;
begin
  ShowMessage('Free!');
end;

procedure TMyInterface.DoSomething;
begin
  //...
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Value: IMyInterface;
begin
  //Wenn der Aufruf auf diese Weise erfolgt, wird das Objekt NICHT frei gegeben.
  Machwas(TMyInterface.Create);

  //So wird das Objekt korrekt frei gegeben
  Machwas(TMyInterface.Create as IMyInterface);

  //so wird das Objekt auch korrekt frei geben
  Value := TMyInterface.Create;
  Machwas(Value);
end;

procedure TForm1.Machwas(const AValue: IMyInterface);
begin
  AValue.DoSomething;
end;
Ist das logisch? Hätte ich bisher anders erwartet... da mir aber der Speicher voll lief, wurde ich eines besseren belehrt.
Andreas Blenk
  Mit Zitat antworten Zitat