1

介绍

我发现我的代码泄漏了TInterfacedObject我作为接口引用保存的一个实例的内存。尽管我将引用变量重置为nil使用后,但它仍然存在。

泄漏的对象是类TMasterObject,它实现了两个接口IInterfaceXIInterfaceY. 对象的引用保存在一个类型为 的变量中IInterfaceY

TMasterObject的实施IInterfaceX纯属巧合。因为它有两个实例TSomeObject,需要引用这个接口,所以我也实现了它TMasterObject

MCVE/SSCCE

program InterfaceDependencies;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  IInterfaceX = interface end;

  IInterfaceY = interface end;

  TSomeObject = class(TObject)
    FReference: IInterfaceX;
    constructor Create(AReferenceX: IInterfaceX);
  end;

  TMasterObject = class(TInterfacedObject, IInterfaceX, IInterfaceY)
    FObjectA: TSomeObject;
    FObjectB: TSomeObject;
    constructor Create;
    destructor Destroy; override;
  end;

{ TSomeObject }

constructor TSomeObject.Create(AReferenceX: IInterfaceX);
begin
  FReference := AReferenceX;
end;

{ TMasterObject }

constructor TMasterObject.Create;
begin
  FObjectA := TSomeObject.Create(Self); // increments "FRefCount" by 1
  FObjectB := TSomeObject.Create(Self); // increments "FRefCount" by 1
end;

destructor TMasterObject.Destroy;
begin
  FObjectA.Free;
  FObjectB.Free;

  inherited;
end;

var
  LMasterObject: IInterfaceY;
begin
  try
    LMasterObject := TMasterObject.Create;
    // 'TMasterObject(LMasterObject).FRefCount' is now "3" because of 'FObjectA.FReference' and 'FObjectB.FReference'
    LMasterObject := nil; // decrements 'TMasterObject(LMasterObject).FRefCount' by 1
    // 'LMasterObject' is not destroyed because 'TMasterObject(LMasterObject).FRefCount' is still "2"
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

问题

可以使用哪些策略

  1. 解决这个特定的问题和
  2. 以后避免此类问题?
4

0 回答 0