Delphi: object aggregation and memory leak using attribute [weak]

I want to build a class TParentcontaining several child objects using aggregation. Some of the facilities are independent, while some of them may also be dependent on other children. All child objects must have a reference to the parent. I also want to use interfaces where possible.

For this purpose I use TInterfacedObjectfor TParentand TAggregatedObjectfor children. Since both the child and the parent know about each other, I use weak links to avoid loop dependencies. In fact, this behavior is already defined in TAggregatedObject. Everything works fine when I use only independent child objects ( TIndependantChild).

The problem occurs when the child also depends on other children, see constructor TDependantChild. I save the link to another child in the fChild variable, which is tagged with a tag [weak]entered in Delphi 10 Berlin. FastMM4 reports memory leaks at shutdown:

enter image description here

An access violation leading to is also violated System.TMonitor.Destroy, but this only happens when FastMM4 is in use and ReportMemoryLeaksOnShutDown is True.

program Project1;

{$APPTYPE CONSOLE}

uses
  FastMM4,
  System.SysUtils;

type
  IParent = interface
  ['{B11AF925-C62A-4998-855B-268937EF30FB}']
  end;

  IChild = interface
  ['{15C19A4E-3FF2-4639-8957-F28F0F44F8B4}']
  end;

  TIndependantChild = class(TAggregatedObject, IChild)
  end;

  TDependantChild = class(TAggregatedObject, IChild)
  private
    [weak] fChild: IChild;
  public
    constructor Create(const Controller: IInterface; const AChild: IChild); reintroduce;
  end;

  TParent = class(TInterfacedObject, IParent)
  private
    fIndependantChild: TIndependantChild;
    fDependantChild: TDependantChild;
  public
    constructor Create;
    destructor Destroy; override;
  end;

{ TParent }

constructor TParent.Create;
begin
  fIndependantChild := TIndependantChild.Create(Self);
  fDependantChild := TDependantChild.Create(Self, fIndependantChild);
end;

destructor TParent.Destroy;
begin
  fDependantChild.Free;
  fIndependantChild.Free;
  inherited;
end;

{ TDependantChild }

constructor TDependantChild.Create(const Controller: IInterface; const AChild: IChild);
begin
  inherited Create(Controller);
  fChild := AChild;
end;

var
  Owner: IParent; 

begin
  ReportMemoryLeaksOnShutDown := True;
  Owner := TParent.Create;
  Owner := nil;
end.

I found that using [unsafe] instead of [weak] solves the problem, but according to delphi help

It ([insecure]) should only be used outside the system unit in very rare situations.

Therefore, I am not sure what I should use [unsafe]here, especially when I do not understand what is happening.

, ?

+6
1

FastMM4 , HashMap, .

[REGRESSION XE2/10.1 Berlin]

- Delphi 10.1 , FastMM4.

[weak], [unsafe].


, [unsafe] . , [unsafe] , , [unsafe] .

, [unsafe], , [unsafe], , .

, , [unsafe] , , , , .

[unsafe] , , , , .

[weak] [unsafe] - , , , .

  TDependantChild = class(TAggregatedObject, IChild)
  private
    [unsafe] fChild: IChild;
+4

All Articles