【问题标题】:iOS app with ARC, find who is owner of an object带有 ARC 的 iOS 应用程序,查找对象的所有者
【发布时间】:2012-12-15 18:54:03
【问题描述】:

我正在编写一个使用 ARC 的应用程序,目前似乎存在一些内存泄漏。谷歌搜索我发现了一些关于如何使用 Inspector 的提示。在那里我可以看到一些类的实例的大量分配,我还可以看到一些关于如何分配对象以及如何更改保留计数的调用堆栈。

但我似乎看不到完整的调用堆栈,所以我不知道最终谁拥有该对象。在我看来,这个所有者没有释放对象(或拥有可疑对象的对象)。

谁能给我一个提示来寻找分配对象的所有者?

还请注意,对象并未标记为“泄漏”,而是已分配。在我看来,随着不断分配新对象,这些对象似乎被泄露了。

对于如何最好地继续并找到可疑泄漏的任何进一步帮助表示感谢。

【问题讨论】:

  • 与非 ARC 相同,arc 不改变所有者权限
  • 回到手头的问题:你能告诉我们更多关于你的代码的信息吗?你在呼唤 CoreFoundation 对象吗?你能提供你认为有东西泄漏的线路吗?我认为示例代码在这里会有所帮助。
  • @Daij-Djan 回复您的评论“arc 不会改变所有权”。你当然是对的,但我可能会争辩说 ARC 实际将所有权正式化了一点(强制执行方法命名约定以指定所有权何时转移,何时不转移,即前缀 allocnew 的存在与否,copy,或mutableCopy。)

标签: ios memory automatic-ref-counting memory-leaks


【解决方案1】:
  1. 就谁“拥有”一个对象的学术问题而言,这只是维护对该对象的strong 引用的人。

  2. 在您的应用程序中查找泄漏方面,您可以在分析应用程序时使用 Instruments 中的“泄漏”工具(在 Xcode 的“产品”菜单上选择“配置文件”)。

  3. 如果它没有出现在“泄漏”中,那么您似乎必须确定它是否是一个强引用循环(以前称为保留循环),一些简单的逻辑错误(例如一些循环视图控制器中的引用、缓存大对象等)或一些与 Core Foundation 相关的问题(ARC 不承担所有权,除非您小心使用 CFBridgingRelease()__bridge_transfer)。

  4. 在使用 Instruments 查找分配源方面,对我帮助最大的两个技巧是:

    • 用鼠标单击拖动(在 Xcode 6 之前的版本中,您必须按住 option 键同时执行此操作)以突出显示时间线的一部分,以确定您想要检查。您可能希望专注于分配中的一个高峰。例如,我在分配中发现了一个凹凸,并将其突出显示(这是一个非常简单的示例,我在 viewDidLoad 中创建了一个巨大的数组,但希望它能给您带来想法):

    • 当您通过调用树进行检查时,选择“隐藏系统库”以专注于您的代码通常很有用。如果您双击 Instruments 中的方法名称(在我的示例中,此处为 viewDidLoad),Instruments 将显示您正在执行分配的代码:

    然后,您可以双击相关的方法列表,它会将您精确地带到执行分配的代码。

虽然这并不能表明您是在哪里发生了泄漏(即强引用循环的位置或您未能释放它的位置),但这种分析通常可以帮助您追踪泄漏对象的实例化位置,即是追查问题的第一步。


如果你真的必须弄清楚谁“拥有”一个对象(即对象的强引用(或保留)发生在哪里),Xcode 8 有一个新的对象图功能。因此,调试应用程序,然后点击调试栏中的“调试内存图”图标(下方红色圆圈)。完成此操作后,您可以在左侧选择一个对象,然后您可以看到显示该对象所有权声明的对象图:

以上说明所选图像具有强引用,其中显示它的UIImageView,而且 ViewController 也保持强引用。

在早期的 Xcode 版本中,配置应用程序以通过 Instruments 运行它并选择“记录引用计数”选项。在 Xcode 6 中,它位于最右侧面板的“记录设置”选项卡上:

在 Xcode 5 及更早版本中,您必须单击分配工具旁边的 信息按钮才能看到此“记录引用计数”选项:

无论如何,您可以转到“分配摘要”,深入了解一些未释放的对象(在“分配”工具中查看对象时,单击对象地址旁边的右箭头 ),然后然后您将看到相关对象的保留和释放列表,如上所示。但是,只有在分析应用程序之前选择“记录引用计数”,这才会被捕获。

习惯这种方式跟踪保留计数需要一段时间,但如果您绝对需要知道强引用是在哪里建立的,“记录引用计数”选项可以帮助您。

【讨论】:

  • 感谢您的解释,有了这些提示,我可以进一步缩小我认为的问题所在。我还不清楚有问题的行为,但我会针对那个问题提出一个新问题,因为它现在更具体了。
  • @TorstenMohr 非常好。我会留意你的后续问题(或者,更好的是,我希望你能解决它!)。并感谢您接受我的回答。
  • 问题与我在另一个线程中分配的对象有关,我没有使用@autoreleasepool,就这么简单。
  • 超级棒 - 特别是显示保留历史的技巧。为什么这个非常有用的功能会像这样隐藏起来,甚至默认都没有打开??!
  • 这个“调试内存图”真的很有前途。然而,它仍然存在许多缺陷:例如,它不跟踪泛型类中的对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-06
  • 2012-10-10
相关资源
最近更新 更多