2020-03-19【內(nèi)存管理】

內(nèi)存管理

  • 內(nèi)存布局
  • 內(nèi)存管理方案
  • 數(shù)據(jù)結(jié)構(gòu)
  • ARC & MRC
  • 引用計數(shù)
  • 弱引用
  • 自動釋放池
  • 循環(huán)引用

1.內(nèi)存布局

  • 內(nèi)核區(qū)
  • stack棧(向下增長):方法調(diào)用
  • heap堆(向上增長):通過alloc等分配的對象
  • bss: 未初始化的全局變量、靜態(tài)變量等。
  • data:已初始化的全局變量等
  • text:程序代碼

2.內(nèi)存管理方案

  • TaggedPointer(NSNumber等小對象)
  • NONPOINTER_ISA(64位架構(gòu))
  • 散列表
    • 一個復(fù)雜的數(shù)據(jù)結(jié)構(gòu),其中包含了弱引用表+引用計數(shù)表

2.1 NONPOINTER_ISA

arm64架構(gòu)

  • 0:indexed標(biāo)志位
    • 為0代表當(dāng)前指針是一個純isa指針,里面內(nèi)容直接代表了當(dāng)前對象的類對象的地址
    • 為1代表:除了當(dāng)前對象的類對象的地址,還有一些內(nèi)存管理數(shù)據(jù)(非指針isa)
  • 1:has_assoc當(dāng)前對象是否有關(guān)聯(lián)對象 0 沒有 1有
  • 2:has_cxx_dtor 當(dāng)前對象是否使用了c++相關(guān)代碼
  • 3~35(33位):shiftcls 當(dāng)前對象的類對象的內(nèi)存地址
  • 36~41(6位):magic
  • 42:weakly_referenced 當(dāng)前對象是否有弱引用指針
  • 43:deallocating 當(dāng)前對象是否正在進行dealloc
  • 44:has_sidetable_rc 當(dāng)前對象是否在散列表里(當(dāng)前isa指針,所存儲的引用計數(shù)達到上限)
  • 45~63:extra_rc 額外引用計數(shù)的存儲

2.2 散列表方式

SideTables()結(jié)構(gòu),哈希表

  • 對應(yīng)多個SideTable
  • SideTable 包含
    • spinlock_t 自旋鎖
    • RefcountMap 引用計數(shù)表
    • weak_table_t 弱引用表

2.3 分離鎖

  • 為啥用多個SideTable? 為了效率
  • 分離鎖:可以并發(fā)執(zhí)行引用計數(shù)改變,但是同一個表只能按順序

2.4 怎樣實現(xiàn)管束分流

SideTables本質(zhì)是一張Hash表

3. 數(shù)據(jù)結(jié)構(gòu)

  • spinlock_t 自旋鎖
  • RefcountMap 引用計數(shù)表
  • weak_table_t 弱引用表

3.1 Spinlock_t 自旋鎖

"忙等"鎖
適用于輕量訪問

3.2 RefcountMap 引用計數(shù)表

hash表實現(xiàn), 插入、獲取 通過同一個函數(shù)

size_t
0:weakly_referenced 是否弱引用
1:deallocating 是否正在dealloc
2~63:RC

3.2 weak_table_t 引用計數(shù)表

key --Hash函數(shù)--> Value(weak_entry_t)

4 MRC & ARC

4.1 MRC 手動引用計數(shù)

  • alloc
  • retain
  • release
  • retainCount
  • autorelease
  • dealloc(MRC要寫super,ARC不寫)

4.2 ARC 自動引用計數(shù)

  • ARC是LLVM和Runtime協(xié)作的結(jié)果
  • ARC禁止調(diào)用4.1中的標(biāo)紅函數(shù)
  • ARC中新增weak、strong

5 引用計數(shù)管理

實現(xiàn)原理分析

  • alloc
  • retain
  • release
  • retainCount
  • dealloc

5.1 alloc

c函數(shù)calloc,此時并沒有設(shè)置引用計數(shù)為1,但是為啥獲取的retainCount是1要看retainCount的實現(xiàn)

5.2 retain

// 找到對應(yīng)的引用計數(shù)表 hash查找
SideTable& table = SideTables()[this];
// 獲取當(dāng)前引用計數(shù)  hash查找
size_t& refcountStroage = table.refcnts[this];
// 自增
refcountStroage += SIDE_TABLE_RC_ONE;

5.3release 實現(xiàn)

// 找到對應(yīng)的引用計數(shù)表 hash查找
SideTable& table = SideTables()[this];
// 獲取當(dāng)前引用計數(shù)  hash查找
RefcountMap::iterator it = table.refcnts.find(this);
// 自減
it->second -= SIDE_TABLE_RC_ONE;

5.4retainCount 實現(xiàn)

// 找到對應(yīng)的引用計數(shù)表 hash查找
SideTable& table = SideTables()[this];
size_t refcnt_result = 1;
// 獲取當(dāng)前引用計數(shù)  hash查找
RefcountMap::iterator it = table.refcnts.find(this);
// 1+引用計數(shù)右便宜然后
refcnt_result += it->second >> SIDE_TABLE_RC_SHIFT;

5.5 dealloc 實現(xiàn)

st=>start: 開始
e=>end: 結(jié)束
op=>operation: _objc_rootDealloc()
op0=>operation: rootDealloc()
cond=>condition: 是否可以釋放?
op1=>operation: c函數(shù)free()
op2=>operation: object_dispose()
st->op->op0->cond
cond(yes)->op1->e
cond(no)->op2->e

是否釋放的5個判斷條件

  • nonpointer_isa
  • weakly_referenced
  • has_assoc
  • has_cxx_dtor
  • has_sidetable_rc
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、內(nèi)存布局 stack:方法調(diào)用 heap:通過alloc等分配對象 bss:未初始化的全局變量等。 data:...
    AKyS佐毅閱讀 1,722評論 0 19
  • 內(nèi)存布局 stack(棧區(qū)): 方法調(diào)用 heap(堆區(qū)):通過alloc等分配的對象 bss:未初始化的全局變量...
    Jimmy_L_Wang閱讀 735評論 1 3
  • iOS中內(nèi)存管理機制是開發(fā)中一項很重要的知識,了解iOS中內(nèi)存管理的規(guī)則不管是在開發(fā)中還是在學(xué)習(xí)中都能很大程度的幫...
    Mr_Atom閱讀 3,487評論 1 4
  • 原文鏈接OC內(nèi)存管理--引用計數(shù)器 更新于2020-02-14 更新Tagged Pointer的知識點 引用計數(shù)...
    NeroXie閱讀 2,409評論 0 6
  • iOS中內(nèi)存管理機制是開發(fā)中一項很重要的知識,了解iOS中內(nèi)存管理的規(guī)則不管是在開發(fā)中還是在學(xué)習(xí)中都能很大程度的幫...
    Horson19閱讀 1,255評論 0 4

友情鏈接更多精彩內(nèi)容