一铲敛、引用計數(shù)值存儲位置
OC對象的引用計數(shù)值存儲在對象的isa指針中乡恕,isa的結(jié)構(gòu)如下:
isa結(jié)構(gòu)體:
union isa_t
{
struct {
...
uintprt_t has_sidetable_rc; // 引用計數(shù)是否存在sidetable中
uintprt_t extra_rc ; // 存儲的值為引用計數(shù)值-1
}
}
如果has_sidetable_rc==0疮胖,引用計數(shù)值就存儲在extra_rc中;如果has_sidetable_rc ==1设易,表示計數(shù)值超出了extra_rc 的存儲范圍(19個字節(jié))逗柴,此時計數(shù)值存儲在sidetable中。
sideTable結(jié)構(gòu):
struct SideTable {
spinlock_t slock;
RefcountMap refcnts;
weak_table_t weak_table;
}
sideTable的refcnts存儲著引用計數(shù)顿肺,refcnts是個散列表戏溺,存儲數(shù)據(jù)是以對象地址為key,引用計數(shù)值為value存儲屠尊。sideTable是靜態(tài)數(shù)據(jù)旷祸,獲取某個對象引用計數(shù)值時,通過對象地址讼昆,在靜態(tài)的sideTable表中進(jìn)行查找肋僧。
二、如何做到自動釋放的
- 工程的main入口有一個autoReleasePool控淡,每個線程內(nèi)部也自帶了autoReleasePool嫌吠。主線程的runloop循環(huán)時會創(chuàng)建一個autoreleasePool,結(jié)束時會會觸發(fā)pool里的內(nèi)存釋放邏輯掺炭,處理完成后銷毀該autoreleasePool辫诅,下個循環(huán)開始時會創(chuàng)建新的pool。子線程不會一直創(chuàng)建涧狮、銷毀pool炕矮。
- arc下的對象初始化后么夫,編譯器會自動往后面追加autorelease標(biāo)識,程序運行時就會把這個對象存儲在最近的autoReleasePool中肤视。autoReleasePool要傾倒時档痪,會檢測里面的對象是否有引用計數(shù)為0的,有則觸發(fā)改對象的dealloc邏輯
三邢滑、Dealloc
引用計數(shù)為0時腐螟,會觸發(fā)dealloc方法,dealloc過程是先子類->父類...->NSObject困后。
dealloc做的工作包括:
1. C++函數(shù)釋放: objc_cxxDestruct
2. 移除關(guān)聯(lián)屬性:_object_remove_assocations
3. 將弱引用自動設(shè)置nil: weak_clear_no_lock(&table.weak_table,(id)this)
4. 引用計數(shù)處理:table.refcnts.erase(this)
5. 銷毀對象:free(obj)