在 CocoaTouch (iPhone OS) 中,如何查找/消除 Instruments Leak 工具找不到的泄漏?

Posted

技术标签:

【中文标题】在 CocoaTouch (iPhone OS) 中,如何查找/消除 Instruments Leak 工具找不到的泄漏?【英文标题】:In CocoaTouch (iPhone OS) how do I find/eliminate leaks that the Instruments Leak tool doesn't find? 【发布时间】:2010-09-21 20:36:44 【问题描述】:

我有一个在模拟器中运行良好的 iPhone 应用程序。它通过摆脱并非绝对必要的所有内容来很好地响应内存警告。当我在设备上运行它时,它运行良好。但是经过一定量的使用后,它会因错误代码 101 而崩溃 - 据我所知,这是操作系统因内存使用而杀死它。我可以看到内存警告(我正在记录它),我的应用程序对其作出响应,但此后不久就死了。

如果我查看 Instruments 中的应用程序(在设备上或在 sim 中),它没有发现任何泄漏。此外,净内存使用量在 600-700k 字节范围内。从我的应用程序的不同视图转换会增加内存使用量(正如预期的那样),但是当视图和控制器被释放并解除分配时,内存使用量永远不会像以前那么低。但是,加法通常只是 1000-2000 字节范围内的内容。因此,虽然 Leaks 显示没有泄漏,但我怀疑某处存在问题。我还查看了我正在分配的所有对象,所有这些对象似乎都按预期被回收了。我看到的唯一不断增加的对象是 GeneralBlock-N(其中 N 是某个数字)

我不应该关注 Instruments 的净使用数字吗?尝试诊断问题的下一步是什么?

添加:我不会调用 malloc() 或任何会返回我负责的缓冲区的 CoreFoundation 库。我所做的唯一非 Obj-C 调用是将语句记录到 NSLog。

【问题讨论】:

您是否以其他方式分配内存而不是释放它?例如使用 CoreFoundation 例程或调用 malloc() 或其他一些返回您负责的内存缓冲区的系统调用? 【参考方案1】:

一个快速尝试的方法是运行Clang static analyzer。这将在您的代码中找到您可能遗漏的一些(但不是全部)问题。它在编译时检查代码,所以它绝不是万无一失的,但几乎肯定会发现最明显的问题。

【讨论】:

+1 表示 Clang。它发现了很多我错过的内存泄漏。这是我在努力设置时有用的教程:oiledmachine.com/posts/2009/01/06/…【参考方案2】:

您还应该使用内存监视器工具运行您的应用程序,以查看设备上的整体系统使用情况。

【讨论】:

很抱歉,如果原始问题中不清楚,但我也试过了。这就是告诉我净使用量在 600-700k 字节范围内的原因。而且我可以在该工具中看到我的所有对象都被清理了。 最后一条评论——我一直在使用 ObjectAlloc。非常感谢您的提示 - 内存监视器确实显示我正在使用大量内存。现在我需要找出原因…… 仅仅因为您没有创建自己的基础对象并不意味着它们不会因为 NSArray 或 NSURLConnection 之类的东西而为您创建【参考方案3】:

Leaks 只查找未被任何东西引用但仍被保留的内存。

你看到的是你保留了记忆,并且仍然被某些东西引用。

要特别注意的一件事是,如果您将一个类的引用作为委托传递给其他东西,那么您可以在您的 dealloc 方法中释放它。

同样,如果您订阅了任何通知,您应该在 viewWillDisappear 中取消订阅:(如果您在视图控制器中使用常规取消订阅方法,请不要忘记重新订阅内存警告通知。

计时器也是如此,当视图消失时停用它们,并在视图返回时重新启用它们(当然,除非您需要在应用程序运行的整个过程中运行计时器)。

基本上对您提供类引用的任何内容都持怀疑态度,并尝试找出如何尽可能消除该链接(在 dealloc 或 viewWillDisappear: 中:或两者兼而有之)。

【讨论】:

【参考方案4】:

以下是我所学知识的摘要(感谢一些出色的答案和 cmets):

对象分配与内存使用不同。我关于 ObjectAlloc 的净字节元素的问题的答案是,您不应该关注它——至少在确定您正在使用的内存量问题或导致它崩溃的原因时不应该关注它。它并不能反映您的应用程序的真实内存使用情况。 我的业余猜测是 ObjectAlloc 只显示直接对象本身占用的内存。因此,如果您有一个 UIImageView,它只占用少量字节来存储各种属性,但它可能指向内存中的图像,占用大量空间。因此,查看 ObjectAlloc 仅有助于确保您没有创建和保留对象,它不会让您了解您正在使用多少内存或在崩溃之前可以使用多少。 MemoryMonitor 将为您提供总内存使用情况。您可以使用 Instruments 窗口右下方的搜索工具将其限制为仅查看应用的使用情况。 ObjectAlloc 和 Memory Monitor(以及 Leaks 工具)都是 Instruments 的插件 - 以防其他人不明白。您可以通过运行 -> 使用性能工具开始从 XCode 中启动仪器。进入 Instruments 后,您可以打开库并添加新插件来监控不同方面的性能。

【讨论】:

太棒了。这是否意味着你已经解决了?还是这还在运行? 仍然是一个错误 :( 我在这里问了一个更具体的问题 - ***.com/questions/289360/… 我已经修复了我的特定错误 - 上述 URL 包含解决方案【参考方案5】:

要寻找的一件事是循环引用。

(我不希望这听起来很傲慢——只是想确保我说的很清楚:)如果对象 a 指的是对象 b 和对象 b 指的是对象 a,可能没有报告“泄漏”,因为所有内存仍被引用 - 但这可能是一个孤立的对象岛,与您的应用程序分离并且永远无法回收。当然可能涉及到更多的对象(abbcc 指的是 a 等)。

如果您在某处构建对象图,并且有任何反向或交叉引用,请确保在释放根时打破圆圈(有不同的方法。最简单的可能是确保每个有问题的类都有一个 releaseAll 方法或类似方法——它在它的子对象上调用 releaseAll,然后释放子对象——但这并不总是最好的解决方案。

【讨论】:

以上是关于在 CocoaTouch (iPhone OS) 中,如何查找/消除 Instruments Leak 工具找不到的泄漏?的主要内容,如果未能解决你的问题,请参考以下文章

从 iPhone/CocoaTouch 库中链接库的正确方法

控制主音量 - iPhone、Cocoa Touch

5个步骤,将 storyboard 从 iphone 版转变为 ipad 版

Cocoa Touch:iPad 表格网格布局

Cocoa Touch框架

Cocoa Touch:在月视图日历上布置日期