为啥迁移到 ARC 后我的应用程序充满了内存泄漏?

Posted

技术标签:

【中文标题】为啥迁移到 ARC 后我的应用程序充满了内存泄漏?【英文标题】:Why is my app full of memory leaks after migrating to ARC?为什么迁移到 ARC 后我的应用程序充满了内存泄漏? 【发布时间】:2012-01-13 03:21:56 【问题描述】:

在使用迁移工具将我的应用迁移到 ARC 并解决所有未决问题后,分配工具中的快速测试显示我在应用中执行的几乎所有操作都在泄漏内存

这是一个相当大的应用程序,迁移需要 2 个小时才能完成(包括检查我所做的每一项更改 - 一切看起来都很好!)

我检查了所有编译器标志两次,以确保真正为每个文件和项目级别启用了 ARC。

在迁移到 ARC 之前,我的应用完全没问题。通过多次重复相同的动作来进行 Heapshots 时,绝对没有堆增长。它是 100% 无泄漏的,没有废弃的内存。它是完美的。现在这是一件巨大的泄漏事情,就像没有明天一样。

知道发生了什么吗?

【问题讨论】:

+1,因为这是我正在考虑对我目前正在开发的项目之一做的事情(它不是太大,所以我认为打开 ARC 标志对我来说是一个很好的教育体验)。我想知道在您的特定情况下使用 Instruments(和对象分配模板)是否有用? 请务必先进行备份。幸运的是我做到了。但是我为迁移浪费了几个小时。可能最好手动迁移一个又一个文件并继续在 Instruments 中进行测试。当然,这可能需要几天的工作,所以我认为这对于现有项目是不可行的。仪器不应无用或显示误导性信息。 @openfrog No. “一定要使用好的 [D]VCS。”我推荐 Hg(或 Git)。 :) 保持强引用而不将它们归零?很难说不知道泄漏了什么。 @HotLicks - 我强烈反对。我现在至少在三个生产应用程序中使用它,这些应用程序更适合它。人们遇到的问题不是由于实现中的错误,而是人们正在适应这种内存管理模式的工作方式。虽然您可以等待并让其他人围绕此扩展文档和示例,但该技术本身现在很强大。 【参考方案1】:

您没有在此处显示任何代码来突出显示导致对象在内存中累积的应用程序部分,因此很难针对您的情况提供具体答案。不过,根据我在 Mac 和 ios 上迁移多个项目的经验,我可以提供一些广泛的建议。

在another answer 中,我详细描述了在自动引用计数下您仍需要注意的几个内存管理领域。这里主要关注的是保留周期和 Core Foundation 对象(或其他非 Objective-C 内存分配)。

鉴于您的应用程序在之前的重复操作中没有积累内存,并且通过 ARC 迁移工具干净地移植,与 Core Foundation 的不正确桥接等问题相比,保留周期更可能是问题所在。迁移工具倾向于突出 Core Foundation 的问题区域,并在它们成为问题之前将其捕获。如何处理它们可能很棘手,但你至少知道它们就在那里。

保留周期可能是需要追踪的细微错误。寻找使用强实例变量或属性设置的委托,而不是弱或不安全未保留的委托。检查您对块或基于块的通知观察者的使用,因为它们可以保留对创建它们的对象的引用(特别是在观察者的情况下)并创建循环。检查导航层次结构中的对象,这些对象使用强引用指向更高的对象。

使用 Instruments 追踪通过 Leaks and Allocations 工具积累的特定对象。在后者中,在重复动作之间使用堆镜头来查看每次通过后哪些对象被创建并仍然存在。您还应该能够识别这些对象的分配位置,希望能导致获取不正确的强引用。

Leaks 仪器有一个新的保留周期检测器,可以通过转到下部面板并将“Leaks”弹出窗口更改为“Cycles & Roots”来查看。这并不能解决所有问题,但可以提供帮助。

我现在已将 Mac 和 iOS 上的多个项目移至 ARC,包括一直使用 GC 的 Mac 应用程序,并且在每种情况下,应用程序都因此而变得更好。这个过程暴露了我多年来在内存管理中遗漏的错误,平均减少了大约 3% 的项目代码,并导致我以前垃圾收集的 Mac 应用程序的性能显着提高(我没有对我的 iOS 进行基准测试)还没有)。

【讨论】:

以上是关于为啥迁移到 ARC 后我的应用程序充满了内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章

内存泄漏和僵尸有啥区别?

是啥导致了这种内存泄漏?

.showsPhysics的内存泄漏

平铺 PDF 视图正在泄漏内存(非 ARC)

SoundPlayer 导致内存泄漏?

CALayer导致ARC内存泄漏