15

我已经使用块有一段时间了,我试图了解所有可能的泄漏情况。我已经阅读了很多关于“保留循环循环”的内容,但我认为也许还有其他可能的情况。另外,我在考虑一些简单的情况,比如:如果你在一个块中调用一个块怎么办?如果我们使用 ARC,块内存管理是否不同?如何使用仪器(或其他工具)查找块是否泄漏内存?

4

1 回答 1

26

简短回答:块本身不会引入任何特殊的泄漏问题(除了特殊情况下的保留周期,如下所述)。

长答案:几个想法:

  1. 除了在捕获 self 时未能避免强引用循环导致的保留循环(在 ARC 中也称为强引用循环),实际上并没有其他与块相关的特殊泄漏风险。如果您还记得块保持对它们引用的对象的强引用,那么只需遵循内存管理的标准基本规则即可。

    正如在使用生命周期限定符避免强引用循环中讨论的那样,在 MRC 中,您可以使用__block限定符来解决这些强引用循环,但在 ARC 中,您可以使用__weak限定符。

  2. 如果您将块放入块中,则不会引入任何额外的泄漏风险(除非您编造一些导致强引用循环的循环引用集,这在块内执行块时通常不太可能)。

  3. 块保留它们引用的对象(除非对象是合格的,例如__blockMRC 中的 with 或__weakARC 中的 with)。使用块这一事实与代码是否泄漏无关。这是您选择 ARC v MRC 的功能,以及您是否避免了保留周期,如果使用 MRC,您是否包含了必要的release语句。

  4. 在查找泄漏方面,标准工具都可以正常工作:

    • 特别是在做非 ARC 代码时,静态分析器(shift++或从“产品”菜单中选择“分析” commandB非常有用。

    • Instruments 用户指南中的关于在您的应用程序中查找泄漏的讨论。

    • 有时对于强参考周期,它不会总是被仪器中的泄漏工具标记。此时,有时使用 Instruments 中的分配工具很有用,突出显示您怀疑应该已释放但未释放的分配,它会显示分配该内存的内容。查看带有 ARC 的 iOS 应用程序,查找对象的所有者

    • 如果您想知道某个对象是否被正确释放,向dealloc应该释放的对象添加诊断实现很有用:

      - (void)dealloc
      {
          NSLog(@"%s", __FUNCTION__);
      
          // if non-ARC, remember to include the following line, too:
          //
          // [super dealloc];
      }
      

      这样,当对象被释放时,您会在控制台上看到一条消息。

  5. 如果您担心泄漏,使用 ARC 是(恕我直言)消除许多普通泄漏的最简单方法之一。在非 ARC 代码中通过简单的省略releaseor泄漏非常容易autorelease(尽管不可否认,上面的链接将帮助您找到它们)。由于一个简单的“哦,我忘记了”,在 ARC 中泄漏要困难得多release

参考

于 2013-05-13T16:56:07.230 回答