Objective-C中的自动引用计数不会阻止或最小化什么样的泄漏?
在Mac和iOS平台上,内存泄漏通常是由未释放的指针引起的。 传统上,检查你的分配,复制和保留以确保每个都有相应的释放消息一直是非常重要的。
Xcode 4.2附带的工具链引入了最新版本的LLVM编译器的自动引用计数(ARC),通过让编译器为你编写内存pipe理你的东西,完全消除了这个问题。 这非常酷,它确实减less了大量不必要的,平凡的开发时间,并防止了大量的不小心的内存泄漏,这些泄漏很容易通过适当的保留/释放平衡来修复。 甚至当您为Mac和iOS应用程序启用ARC时,需要对autorelease池进行不同的pipe理(因为您不应再分配您自己的NSAutoreleasePool
)。
但是还有什么其他的内存泄漏不能防止我仍然需要注意?
另外,Mac OS X和iOS上的ARC和Mac OS X上的垃圾收集有什么区别?
您仍需要注意的主要内存相关问题是保留周期。 这发生在一个对象具有强指向另一个的指针时,但是目标对象具有强指向原始的指针。 即使这些对象的所有其他引用都被删除了,它们仍然会保持不变,不会被释放。 这也可以通过一系列对象间接发生,这些对象可能会将链中的最后一个引用回先前的对象。
正因为如此,存在__unsafe_unretained
和__weak
所有权限定符。 前者不会保留它指向的任何对象,而是留下该对象消失的可能性,它指向不良的内存,而后者不保留该对象,并且在其目标被释放时自动将其自身设置为零。 在这两者中, __weak
通常在支持它的平台上更__weak
。
您可以使用这些限定符来处理委托,例如您不希望对象保留其委托并可能导致循环。
另一个与内存有关的重要问题是处理Core Foundation对象和使用malloc()
分配的malloc()
types,如char*
。 ARC不pipe理这些types,只有Objective-C对象,所以你仍然需要自己处理它们。 核心基础types可能特别棘手,因为有时需要桥接匹配的Objective-C对象,反之亦然。 这意味着当CFtypes和Objective-C之间桥接时,控制需要从ARC中来回传输。 一些与桥接相关的关键词已经被添加,Mike Ash在他的冗长的ARC书写中对各种桥接案例进行了很好的描述。
除此之外,还有其他几个不太常见但仍有潜在问题的情况,详细公布的规范 。
许多新的行为,基于保持对象的状态,只要有一个强大的指针,就和Mac上的垃圾收集非常相似。 但是,技术基础是非常不同的。 这种内存pipe理方式不是定期运行垃圾收集器进程来清理不再指向的对象,而是依赖于我们在Objective-C中需要遵守的严格的保留/释放规则。
ARC只需要重复的内存pipe理任务,我们已经做了多年,并将其卸载到编译器,所以我们再也不用担心它们了。 这样,您就没有垃圾收集平台上遇到的暂停问题或锯齿内存configuration文件。 我在垃圾收集的Mac应用程序中遇到过这两个问题,并且很想看看他们在ARC下的行为。
有关垃圾收集与ARC的更多信息,请参阅Chris Lattner在Objective-C邮件列表中的非常有趣的回应 ,他列出了ARC在Objective-C 2.0垃圾收集方面的许多优势。 我遇到了他描述的几个GC问题。
ARC不会帮助你使用非ObjC内存,例如如果你使用malloc()
东西,你仍然需要free()
它。
ARC可以被performSelector:
愚弄performSelector:
如果编译器无法弄清楚select器是什么(编译器将会产生一个警告)。
ARC也会根据ObjC的命名约定生成代码,所以如果你混合使用ARC和MRC代码,你可以得到令人惊讶的结果,如果MRC代码没有做到编译器认为的名字承诺。
由于以下四个问题,我在应用程序中遇到了内存泄漏:
- 在closures视图控制器时不会使NSTimers无效
- 在closures视图控制器时忘记删除任何观察者到NSNotificationCenter。
- 保持强烈的自我参照块。
- 对视图控制器属性中的委托使用强引用
幸运的是,我遇到了以下博客文章,并能够纠正: http : //www.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four-likely-culprits/
ARC也不会pipe理CoreFoundationtypes。 你可以“桥接”他们(使用CFBridgingRelease()
),但只有当你打算将它用作Objective-C / Cocoa对象时。 请注意,CFBridgingRelease只是将CoreFoundation保留计数递减1,并将其移至Objective-C的ARC。