【问题标题】:Delphi class variable going out of scope before class destructor is calledDelphi 类变量在调用类析构函数之前超出范围
【发布时间】:2013-10-20 09:38:48
【问题描述】:

在类变量中使用动态数组来存储调用类析构函数时需要释放的对象是行不通的。

该数组似乎已超出范围并在调用类析构函数之前已被处理掉。 这是设计的吗?

在 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;

【问题讨论】:

  • 不是一个答案,而是一些建议:不要对对象使用数组,而是 TObjectList (generics.collections),当列表超出范围时,它会为您释放对象。
  • 是的,我知道,但是这个泄漏发生在一个开源线程池库中,所以我想知道这是否符合语言的预期,然后再在那里闲逛。
  • 不用担心,在类析构函数之前清理vars,看我的回答

标签: delphi class variables memory-leaks destructor


【解决方案1】:

类析构函数在单元终结之后调用,因此这意味着在调用类析构函数时数组不再存在。在单元完成时,所有托管变量都由 RTL 清理。最后应该没关系,因为它不是真正的泄漏。

Allen Bauer 提供了有关类构造函数/析构函数here 的更多信息。

编辑

显然这是design

【讨论】:

  • 感谢您提供此信息,我会将其更改为 TObjectlist。
【解决方案2】:

这个“设计”已经修复。 Delphi 10 Seattle 的行为与每个人(包括您和我)所期望的一样 - 它在类析构函数之后释放引用计数的类变量。

可能来自 Embarcadero 的某个人最终意识到反过来绝对不酷,尤其是移动平台上的 ARC:D

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

【讨论】:

    猜你喜欢
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 2012-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    相关资源
    最近更新 更多