内存管理-copy,引用计数,delloc
内存管理释义
- 在iOS中,使用引用计数来管理OC对象的内存
- 一个新创建的OC对象引用计数默认是1,当引用计数减为0,OC对象就会销毁,释放其占用的内存空间
- 调用retain会让OC对象的引用计数+1,调用release会让OC对象的引用计数-1
- 内存管理的经验总结
- 当调用alloc、new、copy、mutableCopy方法返回了一个对象,在不需要这个对象时,要调用release或者autorelease来释放它
- 想拥有某个对象,就让它的引用计数+1;不想再拥有某个对象,就让它的引用计数-1
- 可以通过以下私有函数来查看自动释放池的情况
1
extern void _objc_autoreleasePoolPrint(void);
深拷贝、浅拷贝
- 拷贝的目的:产生一个副本对象,跟源对象互不影响
- 修改了源对象,不会影响副本对象
- 修改了副本对象,不会影响源对象
- iOS提供了2个拷贝方法
- copy,不可变拷贝,产生不可变副本
- mutableCopy,可变拷贝,产生可变副本
- 深拷贝和浅拷贝
- 深拷贝:内容拷贝,产生新的对象
- 浅拷贝:指针拷贝,没有产生新的对象
| copy | mutableCopy | |
|---|---|---|
| NSString | NSString 浅拷贝 |
NSMutableString 深拷贝 |
| NSMutableString | NSString 深拷贝 | NSMutableString 深拷贝 |
| NSArray | NSArray 浅拷贝 |
NSMutableArray 深拷贝 |
| NSMutableArray | NSArray 深拷贝 | NSMutableArray 深拷贝 |
| NSDictionary | NSDictionary 浅拷贝 |
NSMutableDictionary 深拷贝 |
| NSMutableDictionary | NSDictionary 深拷贝 | NSMutableDictionary 深拷贝 |
1 | NSString *str1 = [[NSString alloc] initWithFormat:@"test111111111"]; |
引用计数的存储
- 在64bit中,引用计数可以直接存储在优化过的isa指针中,也可能存储在SideTable类中
- refcnts是一个存放着对象引用计数的散列表
weak
weak是弱引用,用weak来修饰、描述所引用对象的计数器并不会增加,而且weak会在引用对象被释放的时候自动置为 nil,这也就避免了野指针访问坏内存而引起奔溃的情况,weak表其实是一个hash(哈希)表 (字典也是hash表),Key是所指对象的地址,Value是weak指针的地址集合。weak通常用于解决循环引用问题。
weak 的实现原理:
- 初始化时:runtime会调用
objc_initWeak函数,初始化一个新的weak指针指向对象的地址。 - 添加引用时:objc_initWeak函数会调用
objc_storeWeak()函数, objc_storeWeak() 的作用是更新指针指向,创建对应的弱引用表。 - 释放时,调用
clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,清理对象的记录。
源码解析
NSObject.mm
1 | struct SideTable { |
objc-weak.h
weak_table_t,weak表
1 | /** |
objc-runtime-new.mm
weak_entry_t
1 | struct weak_entry_t { |
NSObject.mm
objc_clear_deallocating
1 | void |
objc_clear_deallocating该函数的动作如下:
- 1、从weak表中,以dealloc对象为key, 找到对应的weak_entry_t,
- 2、将weak_entry_t中的所有附有weak修饰符变量的地址,赋值为nil
- 3、将weak表中该对象移除
强、弱指针引用
1 | // ARC是LLVM编译器和Runtime系统相互协作的一个结果 |
dealloc
- 当一个对象要释放时,会自动调用dealloc,接下的调用轨迹是
- dealloc
- _objc_rootDealloc
- rootDealloc
- object_dispose
- objc_destructInstance
- erase
源码解析
NSObject.mm
dealloc
1 | // Replaced by NSZombies |
NSObject.mm
_objc_rootDealloc
1 | void |
objc-object.h
rootDealloc
1 | inline void |
objc-runtime-new.mm
object_dispose
1 | /*********************************************************************** |
objc-runtime-new.mm
objc_destructInstance
1 | /*********************************************************************** |
参考
李明杰老师课件- objc源码
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ivan's Blog!
评论






