5

Using dynamic array in a class variable to store objects that need to be freed when the class destructor is called does not work.

The array seems to have gone out of scope and already disposed of before the class destructor is called. Is this by design ?

Example tested in XE5:

type
  TLeakingObject = class
  public
    I : Integer;
  end;

  TTheLeakOwner = class
  public
    class var OutofScopeArray:array of TLeakingObject;
    procedure Add;
    class destructor Destroy;
  end;

procedure TestThis;
var LeakingTest : TTheLeakOwner;
begin
  LeakingTest := TTheLeakOwner.Create;
  try
    LeakingTest.Add;
  finally
    LeakingTest.DisposeOf;
  end;
end;

{ TTheLeakOwner }

procedure TTheLeakOwner.Add;
begin
  setlength(OutofScopeArray, length(OutofScopeArray) + 1);
  OutofScopeArray[length(OutofScopeArray) - 1] := TLeakingObject.Create;
end;

class destructor TTheLeakOwner.Destroy;
var I: Integer;
begin
  // Length(OutofScopeArray) always = 0, gone out of scope before class destructor ??
  for I := 0 to Length(OutofScopeArray) - 1 do
    FreeAndNil(OutofScopeArray[i]);
end;
4

2 回答 2

5

The class destructor is called AFTER unit finalization so this means that the Array no longer exists at the time the class destructor is called. At unit finalization all managed variables are cleaned up by the RTL. In the end it should not matter because it is not really a leak.

Allen Bauer gives some more info about class constructors/destructors here.

EDIT

Apparently this is by design

于 2013-10-12T10:48:18.287 回答
1

This "design" has been already fixed. Delphi 10 Seattle behaves just as everybody (including you and me) expects - it frees reference-counted class variables after the class destructor.

Probably somebody from Embarcadero realized at last that the other way round is absolutely not cool, especially with ARC on mobile platforms :D

See: https://quality.embarcadero.com/browse/RSP-11289

于 2016-01-24T21:19:38.017 回答