4

我一直无法找到我的几个 Delphi 内存管理问题的答案。我可以测试不同的场景(我这样做是为了找出破坏 FreeAndNil 方法的原因),但它需要的时间太长而且很难!但说真的,我也想知道你们(Delphi 开发人员)如何处理这些内存管理问题。

我的问题(请随意提出自己的问题,我相信他们的答案也会对我有所帮助):

  1. FreeAndNil 是否适用于 COM 对象?我的想法是我不需要它,但如果我需要做的只是将它设置为 nil,那么为什么不在 finally 块中保持一致并使用 FreeAndNil 来处理所有事情呢?

  2. 什么是清理静态数组的正确方法(myArr : Array[0..5] of TObject)。我不能 FreeAndNil 它,所以将它设置为 nil 是否足够好(在我对每个对象进行 FreeAnNil 之后我需要这样做吗?)?

多谢你们!

4

4 回答 4

8

COM 对象通过接口引用,您无需执行任何操作即可释放这些对象。编译器负责必要的引用计数逻辑,以确保 COM 对象将在正确的时间被释放。

至于静态数组(或动态数组,就此而言),您也不需要释放它们。如果它们包含对象,则必须在适当的时间释放对象,但数组不会。

此外,永远不要在不是对象引用的任何东西上使用 FreeAndNil。将它与接口或其他变量一起使用可能会损坏内存。最好不要使用它(使用 Free 代替),除非您正在处理需要释放并稍后重用的对象。

于 2010-03-24T19:41:36.260 回答
2

首先,在大多数情况下,FreeAndNil 有点矫枉过正。当您在析构函数之外或在全局(丑陋)变量上释放对象的字段时,这很方便。但大多数时候,只需拨打免费电话就足够了。

如您所知,对象变量实际上是指向对象数据的指针。当您调用 Free 时,该缓冲区被释放(当然,在析构函数运行之后),但 Object 变量仍然指向刚刚释放的内存位置。它被称为“悬空指针”。只要您知道它在该上下文中悬空,拥有悬空指针就不是问题。举个例子:

Procedure Myproc;
var vString : TStringList;
begin
  //Here, vString is "dangling"
  vString := TStringList.Create;
  //Here, vString is valid
  try
    //Do some stuff
  finally
    vString.Free;
  end;
  //Here, vString is "dangling"...  But who care, it's about to go out of scope and we won't use it again.
end;

在您不确切知道何时或如何释放变量的全局变量上调用 FreeAndNil 更有意义。话虽如此,一直调用 FreeAndNil 并没有错(除非在非常紧凑的循环中,您试图获得每一盎司的性能)。

现在,对于 COM 对象......就像 Mason 所说,它们是引用计数的。因此,如果您持有对该接口的唯一引用,则调用MyInterface := nil;将释放它。但是当/如果变量超出范围时,编译器会添加清理代码以确保接口引用减少。因此,如果您试图将内存要求保持在最低限度,请将接口设置为 nil。否则,没那么重要。

至于您的数组...您可以在列表中的每个项目上调用 Free... Optionnaly 将它们设置为 nil 之后。

于 2010-03-24T21:28:12.630 回答
1

关于静态数组,如果您创建了数组的内容,只需释放您创建的那些对象。你不需要做任何特别的事情来清理 myArr 本身使用的空间。

于 2010-03-24T19:27:11.190 回答
1

COM 对象被自动引用计数;一旦变量超出范围或将接口指针作为字段的对象被删除,Delphi 将调用 _Release 并且对象将自行删除。您不需要明确地将任何内容设置为 nil。

对于静态数组,您需要遍历它们并显式释放每个对象。

于 2010-03-24T19:39:42.097 回答