在objective-c中捕获内存泄漏的设计模式?

Posted

技术标签:

【中文标题】在objective-c中捕获内存泄漏的设计模式?【英文标题】:Design pattern for catching memory leaks in objective-c? 【发布时间】:2012-01-24 04:28:47 【问题描述】:

我已阅读 Apple 的内存管理指南,并认为我了解应遵循的做法以确保在我的应用程序中进行正确的内存管理。

目前看来我的代码中没有内存泄漏。但是随着我的代码变得越来越复杂,我想知道是否应该遵循任何特定的模式来跟踪对象的分配和释放。

创建在整个应用程序执行过程中存在的某种全局对象是否有意义,该对象包含某种类型的活动对象的数量?每个对象都可以在其 init 方法中增加其类型的计数,并在 dealloc 中减少它。全局对象可以在适当的时候验证特定类型的计数是否为零。

编辑:我也知道如何使用泄漏,以及如何使用 Xcode 分析项目。发布此帖子的原因是跟踪可能无法通过泄漏检测或分析的案例。

编辑:另外,拥有这样的东西似乎是有意义的,这样可以通过运行检查全局对象的单元测试来及早在构建中检测到泄漏。我想作为一个没有经验的 Objective-c 程序员,我会从其他人的观点中受益。

【问题讨论】:

使用[anObject retainCount]总是可以找到一个对象的retain count,所以你的系统是不必要的。 @gurooj 正如ocumentation for -retainCount 本身所说,您不应该使用该方法来调试内存管理(或其他任何东西)。 【参考方案1】:

每个对象都可以在其 init 中增加其类型的计数 方法,并在 dealloc 中递减。

要做到这一点,您必须执行以下操作之一:1) 在某个公共点覆盖行为,例如 NSObject 的 -init 或 2) 将适当的代码添加到每个单独的指定初始化程序班级。两者似乎都不简单。

全局对象可以在适当的时候验证一个计数是否 特定类型为零或不。

听起来不错,但您能详细说明一下“适当的时间”吗?在程序生命周期的任何给定时间点,您如何知道哪些类应该有零实例?您应该有一个很好的想法,即在程序结束时不应该有任何对象,但在这种情况下 Instruments 可以告诉您同样的事情。

Objective-C 采取了几个步骤来简化内存管理。尽可能使用属性和合成访问器,因为它们本质上是为您管理对象。最近的一项改进是 ARC,它进一步实现了大多数内存管理任务的自动化。您基本上让编译器找出将内存管理调用放在哪里——这就像没有垃圾收集器的垃圾收集。在尝试发明新工具之前学会使用这些工具。

【讨论】:

我目前的项目是一个 iPhone 游戏,每个关卡都包含与之相关的所有对象。因此,当一个级别完成时,它的所有对象都应该被释放,这将是检查计数器的正确时间。我已经使用了合成属性和访问器。我无法将我的项目迁移到 ARC,因为我使用了一些目前无法修改的第三方库。 请记住,如果需要,您可以为单个文件禁用 ARC。【参考方案2】:

不要走那条路……单继承很痛苦。最重要的是,在您认为必须创建一些全局计数器之前,您应该掌握这些出色的工具。 全局计数器已经存在于一些工具中 -- 学习它们!

对抗它的方法是学习如何在编写时正确平衡和管理所有内容。事后看来真的很简单。

ARC 是另一种选择——实际上它只会推迟你的理解。

第一个“设计模式”我建议尽可能使用release 而不是autorelease(尽管通常对过度发布更有用)。

接下来,定期运行泄漏工具/工具并立即修复所有泄漏/僵尸。

第三,边走边学现有工具!这些工具可以做一些非常疯狂的事情,比如记录每个分配和每个引用计数的回溯。您可以暂停程序的执行并查看存在的分配、分配计数、回溯和各种其他统计信息。

【讨论】:

您能多谈谈全球计数器和您正在谈论的其他工具吗? (姓名等?)谢谢。 Instruments.app->Allocations 和heap 是我最常用的计数器。

以上是关于在objective-c中捕获内存泄漏的设计模式?的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C:CGDataProviderCopyData 的内存泄漏

iPhone - Objective-C - 内存泄漏与 initWithArray

Objective-C / 数组中的内存泄漏

如何确定哪些对象持有对导致 Objective-c 内存泄漏的其他对象的引用?

Objective-C:内存泄漏与自动释放的多重分配?

iPhone - SBJsonParser 的另一个 Objective-C 内存泄漏