没有合适的资源?快使用搜索试试~ 我知道了~
iPhone/Mac Objective-C 内存管理教程和原理剖析 初学 objectice-C 的朋友都有一个困惑,总觉得对 objective-C 的内存管理 机制琢磨不透,程序经常内存泄漏或莫名其妙的崩溃。我在这里总结了自己对 o bjective-C 内存管理机制的研究成果和经验,写了这么一个由浅入深的教程。 希望对大家有所帮助,也欢迎大家一起探讨。 此文涉及的内存管理是针对于继承于 NSObject 的 Class。
资源推荐
资源详情
资源评论
iPhone/Mac Objective-C 内存管理教程和原理剖析
前言
初学 objectice-C 的朋友都有一个困惑,总觉得对 objective-C 的内存管理
机制琢磨不透,程序经常内存泄漏或莫名其妙的崩溃。我在这里总结了自己对 o
bjective-C 内存管理机制的研究成果和经验,写了这么一个由浅入深的教程。
希望对大家有所帮助,也欢迎大家一起探讨。
此文涉及的内存管理是针对于继承于 NSObject 的 Class。
一 基本原理
Objective-C 的内存管理机制与.Net/Java 那种全自动的垃圾回收机制是不
同的,它本质上还是 C 语言中的手动管理方式,只不过稍微加了一些自动方法。
1 Objective-C 的对象生成于堆之上,生成之后,需要一个指针来指向它。
ClassA *obj1 = [[ClassA alloc] init];
2 Objective-C 的对象在使用完成之后不会自动销毁,需要执行 dealloc 来
释放空间(销毁),否则内存泄露。
[obj1 dealloc];
这带来了一个问题。下面代码中 obj2 是否需要调用 dealloc?
ClassA *obj1 = [[ClassA alloc] init];
ClassA *obj2 = obj1;
[obj1 hello]; //输出 hello
[obj1 dealloc];
[obj2 hello]; //能够执行这一行和下一行吗?
[obj2 dealloc];
不能,因为 obj1 和 obj2 只是指针,它们指向同一个对象,[obj1 dealloc]
已经销毁这个对象了,不能再调用[obj2 hello]和[obj2 dealloc]。obj2 实际
上是个无效指针。
如何避免无效指针?请看下一条。
3 Objective-C 采用了引用计数(ref count 或者 retain count)。对象的内
部保存一个数字,表示被引用的次数。例如,某个对象被两个指针所指向(引用)
那么它的 retain count 为 2。需要销毁对象的时候,不直接调用 dealloc,而是
调用 release。release 会让 retain count 减 1,只有 retain count 等于 0,系
统才会调用 dealloc 真正销毁这个对象。
ClassA *obj1 = [[ClassA alloc] init]; //对象生成时,retain count
= 1
[obj1 release]; //release 使 retain count 减 1,retain count = 0,d
ealloc 自动被调用,对象被销毁
我们回头看看刚刚那个无效指针的问题,把 dealloc 改成 release 解决了吗?
ClassA *obj1 = [[ClassA alloc] init]; //retain count = 1
ClassA *obj2 = obj1; //retain count = 1
[obj1 hello]; //输出 hello
[obj1 release]; //retain count = 0,对象被销毁
[obj2 hello];
[obj2 release];
[obj1 release]之后,obj2 依然是个无效指针。问题依然没有解决。解决
方法见下一条。
4 Objective-C 指针赋值时,retain count 不会自动增加,需要手动 retai
n。
ClassA *obj1 = [[ClassA alloc] init]; //retain count = 1
ClassA *obj2 = obj1; //retain count = 1
[obj2 retain]; //retain count = 2
[obj1 hello]; //输出 hello
[obj1 release]; //retain count = 2 ? 1 = 1
[obj2 hello]; //输出 hello
[obj2 release]; //retain count = 0,对象被销毁
问题解决!注意,如果没有调用[obj2 release],这个对象的 retain count
始终为 1,不会被销毁,内存泄露。(1-4 可以参考附件中的示例程序 memman-no
-pool.m)
这样的确不会内存泄露,但似乎有点麻烦,有没有简单点的方法?见下一条。
5 Objective-C 中引入了 autorelease pool(自动释放对象池),在遵守一些
规则的情况下,可以自动释放对象。(autorelease pool 依然不是.Net/Java 那
种全自动的垃圾回收机制)
5.1 新生成的对象,只要调用 autorelease 就行了,无需再调用 release!
ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain coun
t = 1 但无需调用 release
5.2 对于存在指针赋值的情况,代码与前面类似。
ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain coun
t = 1
ClassA *obj2 = obj1; //retain count = 1
[obj2 retain]; //retain count = 2
[obj1 hello]; //输出 hello
//对于 obj1,无需调用(实际上不能调用)release
[obj2 hello]; //输出 hello
[obj2 release]; //retain count = 2-1 = 1
细心的读者肯定能发现这个对象没有被销毁,何时销毁呢?谁去销毁它?(可
以参考附件中的示例程序 memman-with-pool.m)请看下一条。
6 autorelease pool 原理剖析。(其实很简单的,一定要坚持看下去,否则
还是不能理解 Objective-C 的内存管理机制。)
6.1 autorelease pool 不是天生的,需要手动创立。只不过在新建一个 ip
hone 项目时,xcode 会自动帮你写好。autorelease pool 的真名是 NSAutorele
asePool。
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
6.2 NSAutoreleasePool 内部包含一个数组(NSMutableArray),用来保存声
明为 autorelease 的所有对象。如果一个对象声明为 autorelease,系统所做的
工作就是把这个对象加入到这个数组中去。
ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain coun
t = 1,把此对象加入 autorelease pool 中
6.3 NSAutoreleasePool 自身在销毁的时候,会遍历一遍这个数组,releas
e 数组中的每个成员。如果此时数组中成员的 retain count 为 1,那么 release
之后,retain count 为 0,对象正式被销毁。如果此时数组中成员的 retain co
unt 大于 1,那么 release 之后,retain count 大于 0,此对象依然没有被销毁,
内存泄露。
6.4 默认只有一个 autorelease pool,通常类似于下面这个例子。
int main (int argc, const char *argv[])
{
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
// do something
[pool release];
return (0);
} // main
剩余10页未读,继续阅读
资源评论
Jewel00
- 粉丝: 9
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 课高分程设计-基于C++实现的民航飞行与地图简易管理系统-南京航空航天大学
- 航天器遥测数据故障检测系统python源码+文档说明+数据库(课程设计)
- 北京航空航天大学操作系统课设+ppt+实验报告
- 基于Vue+Echarts实现风力发电机中传感器的数据展示监控可视化系统+源代码+文档说明(高分课程设计)
- 基于单片机的风力发电机转速控制源码
- 基于C++实现的风力发电气动平衡监测系统+源代码+测量数据(高分课程设计)
- 毕业设计- 基于STM32F103C8T6 单片机,物联网技术的太阳能发电装置+源代码+文档说明+架构图+界面截图
- 基于 LSTM(长短期记忆)(即改进的循环神经网络)预测风力发电厂中风力涡轮机产生的功率+源代码+文档说明
- 基于stm32f103+空心杯电机+oled按键+运动算法
- 《CKA/CKAD应试指南/从docker到kubernetes 完全攻略》学习笔记 第1章docker基础(1.1-1.4)
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功