【问题标题】:Why is Destroy not called?为什么不调用 Destroy?
【发布时间】:2012-05-25 14:11:43
【问题描述】:

鉴于以下 Delphi 代码,FooFree'd on FormClose,但 TFoo.Destroy 没有被调用 - 因此 Bar 不是 Free'd,导致内存泄漏?

我是否在这里遗漏了什么,或者 Foo.Free 在某些时候不应该调用 Foo.Destroy?

type
  TBar = class
  SomeInteger : integer;
end;

TFoo = class
  Bar : TBar;

  constructor Create();
  destructor Destroy();
end;

var
  Foo : TFoo;

implementation

constructor TFoo.Create;
begin
  Bar := TBar.Create;
  Bar.SomeInteger := 2;
end;

destructor TFoo.Destroy;
begin
  Bar.Free;
  Bar := nil;

  showmessage('Destroyed!');
end;

procedure TForm10.FormCreate(Sender: TObject);
begin
  Foo := TFoo.Create;

  showmessage('Foo created');
end;

procedure TForm10.FormDestroy(Sender: TObject);
begin
  Foo.Free;
  Foo := nil;
end;

【问题讨论】:

  • 析构函数 Destroy(); 覆盖;哎呀。
  • 编译器没有警告过你的代码吗?它应该有。关于隐藏同名虚拟方法的一些事情。
  • 永远不要忽略警告。在许多情况下,忽略警告就是忽略错误!

标签: delphi memory-leaks destroy


【解决方案1】:

你必须用 override 标记析构函数的签名。

destructor Destroy(); override;

你应该在析构函数的末尾有inherited。但由于您的类不是从 TObject 以外的任何东西派生的,我怀疑这并不重要。

【讨论】:

  • 似乎我们同时解决了这个问题......当我被允许时,答案将被接受!我以为我尝试过覆盖,但我也将覆盖放在 Create 上,这会产生编译错误。
  • 好的,史蒂夫。 Override 与虚拟方法一起使用。 TObject.Create 不是虚拟的,所以你不能覆盖它。 TObject.Destroy虚拟的。
【解决方案2】:

Destroy 是虚拟的,因此您必须在后代类中覆盖它。

TFoo = class
  Bar : TBar;

  constructor Create();
  destructor Destroy(); override; // must add override here
end;

没有覆盖,你的析构函数永远不会被调用,而是基类。

【讨论】:

  • 谢谢,终于到了。与往常一样,它是一个更大项目的一部分,无法弄清楚发生了什么。有趣的是,简化问题使问题变得……更简单。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 2022-12-21
  • 1970-01-01
  • 1970-01-01
  • 2020-10-06
相关资源
最近更新 更多