【问题标题】:Delphi Memory Management德尔福内存管理
【发布时间】:2011-01-31 10:13:40
【问题描述】:

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

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

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

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

谢谢各位!

【问题讨论】:

  • 欢迎来到 Stack Overflow。当每个帖子都包含 一个 问题时,效果最好。它允许标题和所有答案是具体的,因此没有人知道一个问题的答案可能会因为只解决部分帖子而被否决。请考虑分别发布您的两个问题,特别是因为它们根本不相关。

标签: delphi memory-management pascal


【解决方案1】:

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

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

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

【讨论】:

  • 有人应该写一篇名为“FreeAndNil 被认为有害”的好文章 :)
  • 嗯,我没有看到那个特定的标题,我不认为,但请参阅 Allen Bauer 的 blogs.embarcadero.com/abauer/2010/02/05/38910blogs.embarcadero.com/abauer/2010/02/16/38916
  • 谢谢,我现在遇到了一些免费和零废话...我已经阅读了 2-3 篇建议尽可能使用 FreeAndNil 的文章 :(
  • 是的,有些人非常喜欢它,但 IME 实际上最好尽可能little 使用它。
  • 像“最好不要使用它”这样的声明需要有一个理由。这是一个非常有争议的声明,请参阅 Bauer 博客文章中的 cmets 以获得证据。提问者似乎对 Delphi 中的基本内存管理问题有疑问,再给他一条规则,让他在不了解其背后原理的情况下盲目遵循也无济于事。
【解决方案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 之后。

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-02
        • 2011-10-04
        相关资源
        最近更新 更多