|
|
51CTO旗下网站
|
|
移动端

避免内存泄漏

《iOS和macOS性能优化:Cocoa、Cocoa Touch、Objective-C和Swift》第7章内存:陷阱和优化技巧,本章将围绕这个话题来进行讨论。除此之外,我们将展示一些陷阱,尤其是在Objective-C 代码中经常出现的问题。本节为大家介绍避免内存泄漏。

作者:李俊阳 等译来源:电子工业出版社|2018-07-17 16:27

避免内存泄漏

对于引用计数而言,存在2 种方式导致对象发生内存泄漏:retain 与release的数目不同,或者出现了循环引用的情况。在使用之前讨论过的规则时,对象所有权规则将自行考虑这些问题,只是还需要在dealloc 中发送release 命令。ARC 另外还会自动在dealloc 中生成release 命令。我不懂为什么这个功能会与ARC 捆绑在一起,因为写一个通用的dealloc 例程其实是很简单的。幸运的是,通过简单的代码检查可以很容易地修复在dealloc 中的内存泄漏(把.h 和.m 并排,然后比较ivar 声明和dealloc 方法),实际上,当我用2001 年所创建的通用/自动化的dealloc 方法后,就再也没为这个问题操心过,这个方法在实际操作中很好用,也不必留心对每个类编写dealloc 方法了。(通用的dealloc 方法使用内省机制来寻找对象中的实例变量并释放,此外还使用了异常列表来避免将非保留引用给释放掉。)

这样就只剩下循环引用这个问题了,它无法用上述技术来解决,也无法通过ARC来解决(虽然ARC 提供了相关的工具)。

循环引用是指有一组对象,尽管它们实际上已经不能由循环外的其他对象访问了,但它们彼此引用,便会永不被销毁。幸运的是,只要开发人员细心,循环引用通常可以避免。最常见的就是结构体中的父链接,也就是说通过让父链接不被保留来处理树结构(例如,视图层次中的superview),如图7.1 所示。如果树的根结点被保留,并且子链接足够,那么只要存在对这个树的引用,就可以保证这个对象不被销毁——开发人员只需要记住,在将子结点从树中移除的时候,只需要将其父指针设置为nil 即可。

ARC 能够很好地处理归零弱引用(zeroing weak reference,例如:@property (weak)UIView *superView)。这些引用与其他非保留引用类似,只是在目标对象被释放的时候,归零弱引用自动变为nil,这样就节省了开发人员在追踪这些引用时所花费的时间,并确保空悬指针不存在。

导致循环引用的另一个潜在原因在于,某个对象由不同的部分所组成,但是这些部分又需要对象整体来提供上下文信息。如果无法将回调引用设为非保留状态,那么打破这个循环引用的方法就是将功能分解成单独的对象和引用,如图7.2 所示。

最后要说明一下堆分配闭包(heap-allocated block),特别是在Grand Central Dispatch(GCD)中所使用的闭包,也是导致循环引用的一大原因,因为在GCD 中的闭包会将其内部的对象进行强引用。隐式范围捕获(implicit scope capture)可以让这个问题简单化。

Clang 静态分析器还可以检测潜在的内存泄漏,不过它也很可能发生误报,定期运行它是保证代码整洁的重要方式之一。

喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

Microsoft SQL Server 2005技术内幕:存储引擎

本书是Inside Microsoft SQL Server 2000的作者Kalen Delaney的又一经典著作,是Inside Microsoft SQL Server 2005系列四本著作中的一本。...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊