释放带有内部接口的接口问题。

5

我这里有一段代码:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  IInnerTest = interface (IInterface)
    procedure DoSth;
  end;

  TRekScannerData = record
    Source: Integer;
    Device: IInnerTest;
  end;

  ITest = interface (IInterface)
    procedure DoSth;
  end;

  ATest = class(TInterfacedObject, ITest)
  private
    FInner: Array of TRekScannerData;
  public
    procedure DoSth;
    constructor Create();
    Destructor Destroy();override;
  end;

  AInnerTest = class (TInterfacedObject, IInnerTest)
  private
    FMainInt: ITest;
  public
    constructor Create(MainInt: ITest);
    procedure DoSth;
    Destructor Destroy();override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  test: ITest;

implementation

{$R *.dfm}

{ ATest }

constructor ATest.Create;
begin
  SetLength(FInner, 1);
  FInner[0].Device := AInnerTest.Create(self);
  //<----- Here is the reason. Passing main interface to the inner interface.
end;

destructor ATest.Destroy;
begin
  beep;
  inherited;
end;

procedure ATest.DoSth;
begin
  //
end;

{ AInnerTest }

constructor AInnerTest.Create(MainInt: ITest);
begin
  FMainInt := MainInt;
end;

destructor AInnerTest.Destroy;
begin
  beep;
  inherited;
end;

procedure AInnerTest.DoSth;
begin
  //
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  test := ATest.Create;
  test.DoSth;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  test := nil;
end;

end.

问题在于当test被赋值为nil时,Destroy方法不会被调用; 我希望通过一条语句释放所有内部接口,是否可能?还是需要使用其他方法在将其赋值为nil之前摧毁所有内部结构? 编辑: 类的结构如下:
Var x = ITest(ATest class) has ->
  Inner Interface: IInnerTest(AInnerTest class) which has reference to:
    ITest(ATest class)

将 x 设为 nil 并不会释放所有结构体...


-1 这就是当你发布虚假代码时会发生的事情。一旦你修复了所有虚假代码中的错误,析构函数确实会被调用。因此,请发布真正的代码,可以编译和运行的代码。然后我们才能提供帮助。 - David Heffernan
通常情况下,当实例被释放时,析构函数会被调用。不幸的是,您发布的代码无法编译,我怀疑您在发布中省略了某些代码。 - Ondrej Kelle
@DavidHeffernan 我已经上传了可以编译的代码。与此同时,问题在于将主接口传递给内部接口。但是如何解决这个问题呢? - John
做得好,你的编辑使问题更加清晰。+1 - David Heffernan
1个回答

5
您遇到了循环引用的问题。您实现的 IInnerTest 持有对 ITest 的引用,而您实现的 ITest 又持有对 IInnerTest 的引用。这种循环引用意味着接口引用计数永远无法归零。
解决此问题的常规方法是使用弱引用。以下是一些有用的链接:

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接