1. 內(nèi)存布局
- 保留區(qū) --> 內(nèi)核去 (低~高)
- 代碼段 --> 已初始化數(shù)據(jù)(.data)--> 未初始化數(shù)據(jù)(.bss)(低~高)
- 堆(由低到高) --> 棧(由高到低)(低~高)
- stack:方法調(diào)用
- heap:通過alloc等分配的對象
- bss:未初始化的全局變量
- data:已初始化的全局變量
- text:代碼段
2. 內(nèi)存管理方案
- TaggedPointer
- NONOPOINTER_ISA(64位架構(gòu)下)
- 散列表(SideTable)
- NONPOINTER_ISA(64位)
- [0] indexed: 標(biāo)志位 0 代表純指針空扎, 1 代表指針中包含其他內(nèi)容
- [1] has_assoc: 是否有關(guān)聯(lián)對象
- [2] has_cxx_dior: 當(dāng)前對象是都有 c++ 的相關(guān)內(nèi)容
- [3 ~ 35] shiftcls: 共33位调鬓,表示當(dāng)前對象類對象的指針地址
- [36 ~ 41] magic: 不涉及
- [42] weakly_referenced: 是否有弱引用
- [43] deallocating: 是否正在進(jìn)行 dealloc 操作
- [44] has_sidetable_rc:是否有額外使用SideTable 計算引用計數(shù)內(nèi)容
- [45 ~ 63]extra_rc 在指針中記錄引用計數(shù)
- SideTables() 結(jié)構(gòu)
- 哈希表(快速定位)
- spinlock_t (自旋鎖蒸绩,分離鎖)
- 引用計數(shù)表
- 弱引用表
- Spinlock_t
- Spinlock_t 是 “忙等” 的鎖聪姿。
- 適用于輕量訪問
- RefcountMap(引用計數(shù)表)
- 通過“指針” ptr 通過哈希查找,找到對象的引用計數(shù)
- weak_table_t (弱引用計數(shù)表)
- 哈希表
3. 引用計數(shù)管理
alloc
調(diào)用C函數(shù) calloc-
retain
- 獲取到當(dāng)前對象的 SideTable
- SideTable 獲取當(dāng)前對象的引用計數(shù)值
- 引用計數(shù)值 + 1
-
release
- 獲取到當(dāng)前對象的 SideTable
- SideTable 獲取當(dāng)前對象的引用計數(shù)值
- 引用計數(shù)值 - 1
-
retainCount
- 獲取到當(dāng)前對象的 SideTable
- SideTable 獲取當(dāng)前對象的引用計數(shù)值
- 引用計數(shù)值 + 1
dealloc
當(dāng)前對象是否可以直接釋放一句以下判斷條件
nonpointer_isa
weakly_referenced
has_assoc 是否有關(guān)聯(lián)對象
has_cxx_dtor 是否有C++內(nèi)容涩惑,或是否使用arc管理內(nèi)存
has_sidetable_rc 當(dāng)前對象的引用計數(shù)是否通過sidetable表維護(hù)的
以上全部為否才可以調(diào)用C函數(shù)直接釋放
否則就要調(diào)用object_dispose() 進(jìn)行釋放object_dispose
開始
objc_destructInstance(): c++釋放榕栏、移除關(guān)聯(lián)對象计螺、將弱引用指針置位nil、清除引用計數(shù)
c函數(shù)free()
結(jié)束
4. 弱引用管理
添加弱引用變量的流程
objc_initWeak()
storeWeak()
weak_register_no_lock()
1 通過對象指針hash計算查找
2 如果已經(jīng)存在了弱引用數(shù)組冶忱,則添加
3 如果沒有尾菇,則創(chuàng)建弱引用數(shù)組
清除weak變量,同事設(shè)置為nil
5. 自動釋放池
- runloop將要結(jié)束時調(diào)用pop操作
- 多層嵌套就是多次插入哨兵對象
- 在for循環(huán)中alloc創(chuàng)建了較大的內(nèi)存消耗是囚枪,可手動插入autoReleasePool來釋放內(nèi)存對象
6. 循環(huán)引用
自循環(huán)引用
相互循環(huán)應(yīng)用
多循環(huán)引用
如何破除
避免產(chǎn)生
在合適的時機(jī)手動破除循環(huán)引用
__weak
__block(ARC下會被強(qiáng)引用)
__unsafe_unretained 修飾對象不會增加引用計數(shù)派诬,但是會產(chǎn)生懸垂指針
解決NSTimer的循環(huán)引用問題
NSTimer會被Runloop引用,所以必須手動釋放NSTimer來解除引用链沼。
采用中間對象默赂,同時弱引用NSTimer和對象,當(dāng)對象被釋放后忆植,NSTimer回調(diào)后放可,判斷弱引用對象已經(jīng)釋放為nil,此時則invalidate timer朝刊,將NSTimer置位nil耀里,此時NSTimer也被成功釋放。