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:

 

  1. 在main thread中, 在某个方法中出现大量的autoreleased objects, 为了避免memory footprint的增大, 可以手动创建一些autorelease pool用来drain objects.
  2. 创建新的thread, 并在其中访问了Cocoa, 需要在访问的前创建autorelease pool, 访问结束后drain.

最后一点, 在每个thread中都会维持一个stack, 其中放置着所有在这个thread中创建但未销毁的pool, 每当一个新的pool创建后, 它就位于stack的最顶端,  相应autoreleased object就会放入其中. 当pool drain的时候, 它就会从stack的顶端移除, 并且release掉其包含的objects.

posted on   CodingForever  阅读(214)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 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——大语言模型本地部署的极速利器

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示