前言
现在对象都是自动释放了,但是熟悉一下对象的内存管理有助于我们更好的理解对象的生命周期,所以今天来看一下内存管理方面的东西。
iOS程序内存布局
memory_struct.png- 代码段 编译之后的代码存放区域
- 数据段
- 字符串常量 程序中所有固定的字符串都存放在这里,如果两个 string 持有相同的内容,其实访问的是同一个内存地址的内容
- 已初始化数据 已经初始化的全局变量、静态变量等
- 已初始化数据 已经初始化的全局变量、静态变量等
- 堆 通过 alloc、malloc、calloc 等动态分配的空间,分配的内存空间地址从小到大
- 栈 函数调用开销,比如全局变量。分配内存空间地址从高到低
Tagged Pointer
- 64bit 开始引入的技术,用于优化 NSNumber、NSDate、NSString 等小对象的存储
- 使用 Tagged Pointer 之前,NSNumber 等对象需要动态分配内存,维护引用计数等,NSNumber 指针存储的是堆中的 NSNumber 对象的地址值
- 使用 Tagged Pointer 之后,NSNumber 指针里面存储的数据变成了: Tag+Data,也就是将数据直接存储在指针中
- 当指针不够存储数据时,才会使用动态分配内存的方式来存储数据
- objc_msgSend 能识别 Tagged Pointer,比如 NSNumber 的 intValue 方法,直接从指针中提取数据,节省了以前的调用开销
- 如何判断一个指针是否为 Tagged Pointer
- iOS平台,最高有效位是 1 (第64bit)
- Mac平台,最低有效位是 1
OC对象的内存管理
- iOS中,使用引用计数来管理对象的内存
- 一个新创建的OC对象引用计数默认是1,当引用计数减为0,OC对象就会销毁,释放其占用的内存空间
- alloc、new、copy、mutableCopy、retain 都会使引用计数 +1,release会让OC对象的引用计数-1
- 内存管理的经验总结
- 当调用alloc、new、copy、mutableCopy方法返回了一个对象,在不需要这个对象时,要调用release或者autorelease来释放它
- 想拥有某个对象,就让它的引用计数+1;不想再拥有某个对象,就让它的引用计数-1
- 可以通过以下私有函数来查看自动释放池的情况
-
extern void _objc_autoreleasePoolPrint(void);
copy-mutableCopy.png
-
dealloc 的调用轨迹:
- dealloc
- _objc_rootDealloc
- rootDealloc
- object_dispose
- objc_destructInstance、free
objc_destructInstance 方法内部实现:
objc_destructInstance.png
最后
以上就是本篇的内容,势必会有一些遗漏和错误的地方,欢迎斧正~
网友评论