NSAutoReleasePool
做iPhone应用开发已经2年多了, 但一些基础的概念性问题只是大致了解, 脑袋中有个模糊的概念. 虽然对平时工作开发没什么影响, 不过时间长了, 心里总是有点虚. 所以从现在开始, 每当我遇到一个模糊概念的问题或topic, 我都要写一篇blog来记录分析, 响应之前在网上看过的一个blog签名:好记性不如烂博客.
今天需要记录的是关于NSAutoReleasePool的理解.(大部分内容来自于iOS4.3 Library)
Cocoa的内存管理主要依赖于Reference Counting, 而NSAutoReleasePool就是用来支持它的. autorelease pool中存放的对象会在其自身干枯(drain)时被release.
我们都知道当一个object的release方法被触发时, 这个对象就被销毁了, 再也不能对它有任何引用, 否则就会出现异常. 但如果在销毁它时触发的是autorelease方法, 那这个object就进入了对应的autorelease pool, 它的生命就被延长了(当pool drain时才真正被销毁).
概述
autorelease 是NSObject的一个类方法,它是通过调用[NSAutoreleasePool addObject:self] 来把一个对象添加到自动释放池中的,因为这是一个类方法,所以有必要知道是对哪个对象进行autorelease调用。
NSAutoreleasePool 实例是保存在每一个线程的stack中。当一个新pool创建,它就会进栈。当一个stack被销毁的时候,它就出栈。 使用NSAutoreleasePool类方法时,需要从当前线程中获取stack最上面的pool对象,来获取当前pool。
当找到正确的pool后,调用addObject: 实例方法来将对象添加到pool中。当对象被添加到pool中,其实他是添加到pool中的一个可变数组中去。
当pool被销毁时,pool会遍历可变数组中的所有对象,并发送 release 方法给每一个对象。还有一点额外说明,如果一个pool被销毁,并且这个pool不是stack最上端的,这个pool还会销毁该pool之上的所有pool。
总结
- 没有方法知道一个对象是否已经被自动释放了。
- 如果对象被autorelease 两次,这个对象就会被两次添加到pool中,当pool被销毁,该对象就会被release两次。
- 自动释放池的对象是当当前自动释放池被释放时被释放。pool是当它的代码显性的销毁它时而被销毁。
- 如果在一个线程上autorelease一个对象,并将它传给另一个线程,不会有特殊处理。当第一个线程池被销毁的时候,该对象也会被release, 不管该对象在新线程发生了什么。如果你需要继续保留这个对象,就需要在传递之前retain这个对象。
==================
转自:http://eleda.iteye.com/blog/1108700
在Reference Counting的环境里, Cocoa总是期望在每一个thread都存在一个autorelease pool, 如果不存在, 那些被autoreleased的objects就不会被销毁, 从而产生memory leak. (印象中这种情况下xcode会在console打出warnning信息)
NSAutoReleasePool的初始化与普通的NSObject一样, 都是alloc+init, 不过pool不能被retain, 因为在drain的时候默认就销毁它自身了. 还有一点需要注意的是, 通常在销毁pool的时候用的不是它的release方法, 而是drain! 原因是为了让程序同时兼容Reference Counting内存管理环境 与 Garbge Collection环境, 因为在Garbage Colloection环境中drain的作用是触发collect garbage动作.
一般来说在应用的main thread中, 已经存在了一个autorelease pool. 有两种情况需要开发者自己新建autorelease pool:
- 在main thread中, 在某个方法中出现大量的autoreleased objects, 为了避免memory footprint的增大, 可以手动创建一些autorelease pool用来drain objects.
- 创建新的thread, 并在其中访问了Cocoa, 需要在访问的前创建autorelease pool, 访问结束后drain.
最后一点, 在每个thread中都会维持一个stack, 其中放置着所有在这个thread中创建但未销毁的pool, 每当一个新的pool创建后, 它就位于stack的最顶端, 相应autoreleased object就会放入其中. 当pool drain的时候, 它就会从stack的顶端移除, 并且release掉其包含的objects.
posted on 2015-06-17 15:37 CodingForever 阅读(214) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器