Day12-ARC 本质、Weak 实现、循环引用处理
			
			
		 
		
		
			一、ARC 的本质(Automatic Reference Counting)
ARC 是编译器级别的内存管理机制,由 Clang 编译器在编译时插入 retain/release/autorelease 相关的代码。
核心机制
- 每个对象都有一个 引用计数(retain count)。
- 强引用(strong)+1(retain),释放 -1(release)。
- 引用计数为 0 时,调用 dealloc释放对象。
- ARC 只管理对象内存,不管理 malloc/free 的非对象内存。
二、Weak 的实现原理
__weak 不增加引用计数,用于避免循环引用,自动在对象销毁时置为 nil。
weak_table_t 全局结构
- 存储所有 weak 引用对象与对应指针地址。
- 每个对象记录在一个 weak_entry_t中:
| 12
 3
 4
 
 | struct weak_entry_t {DisguisedPtr<objc_object> referent;
 weak_referrer_t *referrers;
 };
 
 | 
objc_storeWeak(id *location, id obj)
- 清除旧值
- 设置新值,并注册到 weak_table_t
对象销毁时:
- 调用 objc_clearWeakRefs,将所有 weak 指针置 nil
三、循环引用及处理方式
循环引用定义
- 当两个对象互相强引用,引用计数永远不为 0,导致内存泄漏。
解决方法
- 使用 __weak或__unsafe_unretained
- 在 block 中使用 [weak self]或[unowned self]
- delegate 常使用 weak
四、底层实现:引用计数存储与操作
isa_t 结构(64 位系统)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | union isa_t {uintptr_t bits;
 struct {
 uintptr_t nonpointer        : 1;
 uintptr_t has_assoc         : 1;
 uintptr_t has_cxx_dtor      : 1;
 uintptr_t shiftcls          : 44;
 uintptr_t magic             : 6;
 uintptr_t weakly_referenced : 1;
 uintptr_t deallocating      : 1;
 uintptr_t has_sidetable_rc  : 1;
 uintptr_t extra_rc          : 8;
 };
 };
 
 | 
- 引用计数快速路径,最大 255。
- 超过后,引用计数信息存入 SideTable。
SideTable 结构
| 12
 3
 4
 5
 
 | struct SideTable {spinlock_t slock;
 RefcountMap refcnts;
 weak_table_t weak_table;
 };
 
 | 
五、objc_retain 和 objc_release 底层逻辑
objc_retain(id obj)
| 12
 3
 4
 5
 
 | id objc_retain(id obj) {if (obj == nil) return nil;
 if (obj->isa.tryRetain()) return obj;
 return retainSlow(obj);
 }
 
 | 
objc_release(id obj)
| 12
 3
 4
 5
 
 | void objc_release(id obj) {if (obj == nil) return;
 if (obj->isa.tryRelease()) return;
 releaseSlow(obj);
 }
 
 | 
六、__weak 与 __unsafe_unretained 对比
| 特性 | __weak | __unsafe_unretained | 
| 是否增加引用计数 | 否 | 否 | 
| 对象释放后指针 | 自动 nil | 悬垂指针 | 
| 安全性 | 高 | 低 | 
| 性能 | 稍低 | 高 | 
七、调试与优化建议
调试工具
- [object retainCount]
- po [obj retainCount](LLDB)
- 设置环境变量:
| 1
 | export OBJC_PRINT_RETAIN_RELEASE=YES
 | 
优化建议
- weak 有性能开销,频繁使用需谨慎。
- block 捕获 self 时建议使用 [weak self]。
八、总结架构图示(文字版)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | ┌──────────────┐│ ARC 编译器插入 │
 └──────┬───────┘
 ↓
 ┌─────────────┐
 │ isa_t 的 extra_rc │  <───<255 快路径
 └──────┬──────┘
 ↓
 ┌──────────────┐
 │ SideTable 存储引用计数 │
 └──────┬───────┘
 ↓
 ┌─────────────┐
 │ weak_table_t │ ← weak引用管理
 └─────────────┘
 
 |