MRC下的內(nèi)存管理
內(nèi)存中的5大區(qū)域
- 棧區(qū)
這個區(qū)的內(nèi)存保存的是局部變量, 當(dāng)作用域結(jié)束后, 系統(tǒng)就會自動回收內(nèi)存.
局部變量num4 = 0x7fff5fbff7bc
- 堆區(qū)
這個區(qū)是用來程序員通過代碼來申請的空間, 這塊空間會一直保存到程序的結(jié)束, 直到程序員手動來釋放. 內(nèi)存管理只會管理堆區(qū)上的內(nèi)存.
對象小明在堆區(qū)的地址是:0x100400200
- BSS段
這個區(qū)的內(nèi)存主要是用來保存未被初始化的全局變量或靜態(tài)變量, 一旦被初始化后就會將數(shù)據(jù)轉(zhuǎn)移到數(shù)據(jù)段.同樣是系統(tǒng)自動執(zhí)行的.
- 數(shù)據(jù)段
這個區(qū)的內(nèi)存是用來保存全局變量或靜態(tài)變量, 直到程序結(jié)束才會被系統(tǒng)自動回收.
全局變量num1 = 0x1000011f0
靜態(tài)變量num3 = 0x1000011f4
類地址p1 = 0x1000011c8
- 代碼區(qū)
這個區(qū)的內(nèi)存是用來存儲程序中的代碼.
函數(shù)指針 p = 0x100000dd0
內(nèi)存管理的必要性
內(nèi)存中的對象如果不在不用的時候及時的回收, 可以想象對于有限的內(nèi)存來說是不可能實現(xiàn)的.
例如:iPhone的內(nèi)存警告機(jī)制, 內(nèi)存到40M就會警告, 如果到了120M就會閃退.
怎么進(jìn)行內(nèi)存管理
1.相關(guān)概念
如果想對內(nèi)存進(jìn)行管理, 首先必須理解與內(nèi)存管理相關(guān)的概念.
- 僵尸對象與野指針
僵尸對象: 指的是內(nèi)存中的對象已經(jīng)被釋放, 但還沒有被CPU給分配出去.
野指針: C語言中的野指針指的是定義了一個指針但是沒有初始化, 導(dǎo)致指針中存儲的是垃圾值, 指向內(nèi)存中的任意地址.
OC中的野指針指的是指針指向的對象已經(jīng)被回收了, 如果仍有指針指向容易誤操作.
- 內(nèi)存泄漏
內(nèi)存泄漏: 指的是一個應(yīng)該被回收的對象, 沒有得到及時的回收. 這樣的對象會一直存在于內(nèi)存中 直到程序結(jié)束. 這樣的結(jié)果會導(dǎo)致內(nèi)存的泄漏.
- MRC與ARC
MRC: Manual Reference Counting, 指的是Xcode下編寫代碼需要手動對內(nèi)存進(jìn)行管理.
ARC: Automatic Reference Counting, 指的是Xcode下編寫代碼系統(tǒng)會自動的進(jìn)行內(nèi)存管理.
- 引用計數(shù)器
引用計數(shù)器: 所有的OC對象內(nèi)都有一個叫做retainCount的屬性, 這個屬性的默認(rèn)值是1, unsigned long類型.
- dealloc方法
dealloc方法: 所有的OC對象在被回收之前都會系統(tǒng)自動調(diào)用dealloc方法
2.內(nèi)存管理
- 引用計數(shù)器的使用
引用計數(shù)器的默認(rèn)值是1, 調(diào)用類的retain方法使引用計數(shù)器+1, 調(diào)用類的release方法引用計數(shù)器-1. 當(dāng)引用計數(shù)器為0時, 對象就會被回收.
- (instancetype)retain OBJC_ARC_UNAVAILABLE;
- (oneway void)release OBJC_ARC_UNAVAILABLE;
- 野指針與僵尸對象
為了避免野指針指向僵尸對象造成誤操作, 建議將在指針變成野指針后賦值為nil. 在Xcode下也可以打開僵尸對象檢查, 但是這樣會很影響程序的性能, 謹(jǐn)慎使用.
- 內(nèi)存管理原則
- 有對象的創(chuàng)建就要匹配release.
Person *p1 = [Person new];
[p1 release];
- retain的次數(shù)要和release匹配.
Person *p1 = [Person new];
[p1 retain];
[p1 retain];
[p1 release];
[p1 release];
[p1 release];
- 為了代碼的規(guī)整, 誰用了一個對象誰就retain, 誰不用誰就release, 誰負(fù)責(zé)retain, 誰就負(fù)責(zé)release.
- 不要隨便retain, 多一個人使用的時候才retain, 少一個人使用的話就release.
- 單個對象內(nèi)存管理
1. 有對象的創(chuàng)建 就必須要匹配1個release.
2. retain次數(shù)和release次數(shù)一定要匹配.
3. 只有在指針稱為野指針的時候才賦值為nil
4. 在方法中不要隨意的為傳入的對象retain.
- 多個對象內(nèi)存管理
1.當(dāng)一個對象是另一個對象的參數(shù)時候, 重寫setter方法和dealloc方法
2.對象作為參數(shù)需要將舊的對象release, 新的對象retain
3.同一個對象作為參數(shù)被賦值了兩次時會造成內(nèi)存泄漏, 所以重構(gòu)setter方法的時候一定要加入if判斷新舊對象是否為同一個對象
重寫setter和dealloc的標(biāo)準(zhǔn)寫法
- (void)setCar:(Car *)car
{
if(_car != car)
{
[_car release];
_car = [car retain];
}
}
- (void)dealloc
{
[_car release];
[super dealloc];
}
- @property參數(shù)
MRC下:
a: 多線程相關(guān)
atomic: (默認(rèn)值)setter方法加了一把線程安全鎖, 效率低
nonatomic: 建議使用
b: 與生成setter方法的實現(xiàn)相關(guān)
assign: (默認(rèn)值) 生成的setter方法的實現(xiàn)就是直接賦值
retain: 生成的setter就是標(biāo)準(zhǔn)的MRC內(nèi)存管理管理代碼.ps:dealloc內(nèi)的release代碼還需要一樣寫
c: 與生成只讀, 讀寫屬性的相關(guān)
readwrite: (默認(rèn)值)代表同時生成getter和setter
readonly: 只生成getter, 不會生成setter
d: 與生成的getter, setter方法相關(guān)
getter=XXX: 重寫getter的方法名
setter=ooo: : 重寫setter方法的名字
在BOOL類型的參數(shù)中重寫getter
- 類的循環(huán)引用
例如:Person類中有個Book類屬性, 而Book類中又有一個作者(Person)屬性. 這樣在導(dǎo)入頭文件的時候就會出現(xiàn)循環(huán)引用.
解決辦法:
其中一邊不要使用#import引入對方的頭文件.
而是使用@class 類名. 這樣就可以不引用對方頭文件的情況下, 告訴編譯器這是一個類.
@class
作用及含義: 相當(dāng)于向編譯器聲明了一個類, 并沒有實現(xiàn)它.(參考c語言的函數(shù)的聲明)
- 對象間的相互引用
例如:Person類的小明對象有本書<三國>(Book類), <三國>對象有一個作者屬性是小明(Person類), 這個時候就出現(xiàn)了循環(huán)引用.
解決方法:
1端使用retain, 一端使用assign , assign那一邊就不需要release.
ARC下的內(nèi)存管理
ARC概述
Automatic Reference Couunting, 顧名思義是系統(tǒng)會自動幫助我們?nèi)ビ嬎阋糜嫈?shù)器的值, 是WWDC2011和iOS5引入的最大的變革和最激動人心的變化.ARC是新的LLVM3.0編譯器的一項特性,使用ARC,可以說一舉解決了廣大iOS開著所憎恨的手動管理內(nèi)存的麻煩.
ARC管理內(nèi)存的原理
- 強(qiáng)指針與弱指針
默認(rèn)情況下, 我們聲明的指針就是強(qiáng)指針, 或者使用__strong來顯示的聲明一個強(qiáng)類型的指針.
弱指針指的是用__weak修飾的指針, 無論強(qiáng)指針還是弱指針, 作為存儲對象的地址, 并且通過指針操作對象方面上沒有任何區(qū)別, 唯一的區(qū)別是在對象回收上, 如果沒有任何強(qiáng)類型的指針指向的時候, 對象就會回收.
新建一個項目的話系統(tǒng)會默認(rèn)開啟ARC, 使用ARC的過程中, 系統(tǒng)會在編譯的過程中自動的在合適的位置為我們加上
retain, release, autorelease. 對象會在沒有強(qiáng)類型的指針指向的時候被回收掉, 其本質(zhì)還是對象的引用計數(shù)器被減為0了.
ARC與MRC的轉(zhuǎn)換和兼容
ARC和MRC通過命令-fno-objc-arc可以相互兼容, 通過Xcode可以將MRC手動轉(zhuǎn)成ARC, 由于系統(tǒng)的處理過于簡單, 謹(jǐn)慎使用.
ARC與垃圾回收機(jī)制的區(qū)別
垃圾回收機(jī)制GC是在程序的運行期間不斷循環(huán)掃描對象是否無人使用, 如果沒有使用就回收.
ARC是在程序編譯的過程就系統(tǒng)自動的加上了一些內(nèi)存管理代碼.