iOS內(nèi)存管理中引用計數(shù)的學(xué)習(xí)
1.引用計數(shù)的思考方式
- 自己生成的對象,自己持有
- 非自己生成的對象,自己也能持有
- 不在需要自己持有的對象時釋放
- 非自己持有的對象無法釋放
2.引用計數(shù)的實現(xiàn)
1.alloc方法
+ alloc + allocWithZone: class_creatInstance calloc
調(diào)用alloc方法首先調(diào)用allocWithZone:類方法,然后調(diào)用class_creatInstance函數(shù),最后調(diào)用calloc來分配內(nèi)存塊。
2.ratainCount/retain/release 方法
- retainCount __CFDoExternRefOperation CFBasicHashGetCountOfKey
- retain __CFDoExternRefOperation CFBasicHashAddValue
-retainCount __CFDoExternRefOperation CFBasicHashRemoveValue //CFBasicHashRemoveValue 為0時,-release調(diào)用dealloc
各個方法都通過同一個__CFDoExternRefOperation函數(shù),調(diào)用一系列名稱相似的函數(shù)。并且從函數(shù)名看出蘋果采用散列表(引用計數(shù)表)來管理引用計數(shù),表鍵值為內(nèi)存塊地址的散列值。然而GNUStep將引用計數(shù)保存在對象占用內(nèi)存塊頭部的變量中(objc_layout這個結(jié)構(gòu)體中)。
內(nèi)存塊頭部管理引用計數(shù)的好處:
- 少量代碼皆可完成
- 能夠統(tǒng)一管理引用計數(shù)內(nèi)存塊與對象內(nèi)存塊。
引用技術(shù)表管理引用計數(shù)的好處:
1. 對象內(nèi)存快的分配無需考慮內(nèi)存塊頭部
引用計數(shù)表各記錄中存有內(nèi)存塊地址,可從各個記錄追溯到各個內(nèi)存塊。
第二條特征在調(diào)試時很重要,即使出現(xiàn)故障導(dǎo)致對象占用的內(nèi)存塊損壞,但只要引用計數(shù)表沒有被損壞,就能夠確認(rèn)各個內(nèi)存塊的地址
3.autorelease方法
NSAutoreleasePool是通過以AutoreleasePoolPage為結(jié)點的雙向鏈表來實現(xiàn)的。AutoreleasePoolPage是一個C++實現(xiàn)的類,類結(jié)構(gòu)如圖:
- magic 用來校驗 AutoreleasePoolPage 的結(jié)構(gòu)是否完整;
- next 指向最新添加的 autoreleased 對象的下一個位置,初始化時指向 begin() ;
- thread 指向當(dāng)前線程;
- parent 指向父結(jié)點,第一個結(jié)點的 parent 值為 nil ;
- child 指向子結(jié)點,最后一個結(jié)點的 child 值為 nil ;
- depth 代表深度,從 0 開始,往后遞增 1;
- hiwat 代表 high water mark 。
AutoreleasePoolPage每個對象會開辟4096字節(jié)內(nèi)存(也就是虛擬內(nèi)存一頁的大?。藢嵗兞克伎臻g,剩下的空間全部用來儲存autorelease對象的地址。內(nèi)存結(jié)構(gòu)如圖:
在Cocoa框架中,NSRunloop每次循環(huán)過程中NSAutoreleasePool對象被生成或廢棄。在大量產(chǎn)生autorelease對象時,只要不廢棄NSAutoreleasePool那么生成的對象就不能被釋放,在此情況下有時會產(chǎn)生內(nèi)存不足的現(xiàn)象,因此有必要適當(dāng)?shù)纳桑钟泻蛷U棄NSAutoreleasePool。通常在使用Objective-C,無論調(diào)用哪一個對象的autorelease/retain方法,實現(xiàn)上都是調(diào)用NSObject類的autorelease/retain實例方法,但是對于NSAutoreleasePool類,autorelease/retain實例方法已被重寫,因此運行時會出錯(exception)。autorelease實際上把對象的釋放時機交給NSAutoreleasePool管理,使用方法如下:
生成并持有NSAutoreleasePool對象。
NSAutoreleasePool *pool = [NSAutoreleasePool alloc] init]; // 等同于 objc_autoreleasePoolPush()
調(diào)用已分配對象的autorelease實例方法。
id obj = [NSObject alloc] init]; [obj autorelease]; // 等同于 objc_autorelease()obj
廢棄NSAutoreleasPool對象(自動調(diào)用分配對象的release)。
[pool drain]; // 等同于 objc_autoreleasePoolPop(pool)
4.ARC說明
ARC(Automatic Reference Counting)是編譯階段自動做了retain/release,原先需要手動添加處理引用計數(shù)的代碼可以自動地由編譯器完成。ARC并不是GC,不是運行時內(nèi)存管理,不會做malloc/free的工作,它只是一種代碼靜態(tài)分析(Static Analyzer)工具,同一程序中按文件單位可以選擇ARC有效和無效。Core Foundation中的malloc()或者free()等,還是需要自己手動進行內(nèi)存管理。設(shè)置ARC有效的編譯方法如下:
- 使用clang(LLVM編譯器)3.0或以上版本。
- 指定編譯器屬性為”-fobjc-arc“。
3.引用計數(shù)查看
Apple 提供一些方法查看對象的引用計數(shù),但是并不能完全信任這些函數(shù)提供的引用計數(shù)值。對于已釋放的對象一級不正確的對象地址,有時 也返回”1“,在多線程中,因為存在競態(tài)條件的問題,所以取得的的數(shù)值不一定可信。
[object retainCount]; //得到object的引用計數(shù),此方法僅僅適用于MRC _objc_rootRetainCount(obj); //MRC和ARC都適用
相關(guān)文章
iOS利用NSAttributedString實現(xiàn)圖文混排效果示例
iOS7以后,因為TextKit的強大,可以用NSAttributedString很方便的實現(xiàn)圖文混排(主要是利用了NSTextAttachment),所以下面這篇文章主要給大家介紹了關(guān)于iOS利用NSAttributedString實現(xiàn)圖文混排效果的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。2017-10-10詳解Obejective-C中將JSON數(shù)據(jù)轉(zhuǎn)為模型的方法
這篇文章主要介紹了Obejective-C中JSON數(shù)據(jù)轉(zhuǎn)為模型的方法,同時介紹了使用jastor庫的方法,需要的朋友可以參考下2016-03-03iOS給圖片添加濾鏡&使用openGLES動態(tài)渲染圖片詳解及實例
這篇文章主要介紹了iOS給圖片添加濾鏡&使用openGLES動態(tài)渲染圖片詳解及實例的相關(guān)資料,需要的朋友可以參考下2016-10-10IOS開發(fā)仿微信右側(cè)彈出視圖實現(xiàn)
這篇文章主要介紹了IOS開發(fā)仿微信右側(cè)彈出視圖實現(xiàn)的相關(guān)資料,希望通過本文能幫助到大家,讓大家實現(xiàn)這樣類似的功能,需要的朋友可以參考下2017-10-10IOS如何使用CAShapeLayer實現(xiàn)復(fù)雜的View的遮罩效果
這篇文章主要為大家詳細介紹了IOS如何使用CAShapeLayer實現(xiàn)復(fù)雜的View的遮罩效果,感興趣的小伙伴們可以參考一下2016-03-03Objective-C方法的聲明實現(xiàn)及調(diào)用方法
這篇文章主要介紹了Objective-C方法的聲明實現(xiàn)及調(diào)用方法,包括五參數(shù)的方法和單個參數(shù)的方法,結(jié)合實例代碼給大家介紹的非常詳細,感興趣的朋友一起看看吧2024-02-02