OC內(nèi)存管理有兩種模式:
ARC automatic reference counting 自引用用計(jì)數(shù)
MRC manual reference counting 手動(dòng)引用計(jì)數(shù)
在2011年、IOS5之前,OC的開發(fā)只支持MRC模式。
也就是只支持手動(dòng)引用計(jì)數(shù)。
當(dāng)時(shí)每當(dāng)一個(gè)新的指針引用了一塊堆空間(也就是對(duì)象)
就必須手動(dòng)的把此塊堆空間內(nèi)的 retainCount + 1。
具體操作:
Person* p = [Person new];//默認(rèn)就是1 ,所以這里的p不需要手動(dòng)操作。
Person* p2 = p;
[p2 retain];//將retainCount的值+1;
當(dāng)p2指針不使用此堆空間了。要手動(dòng)把 retainCount 值 - 1
[p2 release];
p不用了,也需要release
[p release];
手動(dòng)計(jì)數(shù)器使用規(guī)則:
誰用誰retain,誰不用誰release。
關(guān)于內(nèi)存釋放的本質(zhì):
當(dāng)一塊內(nèi)存釋放的時(shí)候,本質(zhì)上只是給這部分字節(jié)打了標(biāo)簽。并沒有把字節(jié)里的二進(jìn)制數(shù)據(jù)全部清成0或者1.
所以,當(dāng)一塊內(nèi)存說是釋放了,但如果沒有其他的二進(jìn)制數(shù)據(jù)去填充它,那么它的內(nèi)部數(shù)據(jù)是一直存在的。
內(nèi)存釋放,數(shù)據(jù)仍然存在,就會(huì)出現(xiàn)一種僵尸對(duì)象的問題。
什么是僵尸對(duì)象?堆空間已經(jīng)被標(biāo)記清空,能被其他數(shù)據(jù)使用。但此時(shí)此刻,新的二進(jìn)制數(shù)據(jù)還沒有進(jìn)來。
我們此時(shí)用一個(gè)指針指向已經(jīng)標(biāo)記釋放了的堆空間。這個(gè)就叫僵尸對(duì)象和野指針。
At mrc model:
Person* p = [Person new];
[p release];//指針指向的堆空間,在代碼級(jí)別已經(jīng)被釋放。
p.name = @“內(nèi)存就沒有釋放的概念,只是打了可以被其他數(shù)據(jù)填充的標(biāo)簽”;
NSLog(@“%@”,p.name);//但如果沒有其他的數(shù)據(jù)填充這塊空間,所以在某種條件下(沒被其他數(shù)據(jù)填充)數(shù)據(jù)仍然存在??梢岳^續(xù)訪問。
關(guān)于dealloc函數(shù)釋放堆空間。
在手動(dòng)模式下:
1、可以直接調(diào)用dealloc 強(qiáng)制標(biāo)記當(dāng)前堆空間直接被釋放,而不用去管retainCount是否是0.
2、每次調(diào)用release 把 retainCount-1 的同時(shí)會(huì)判斷retainCount的最終值是否是0,是0接著調(diào)用dealloc函數(shù)標(biāo)記當(dāng)前堆空間釋放。
如何在手動(dòng)模式下,避免已經(jīng)被標(biāo)記的堆空間被指針引用并使用呢?
因?yàn)楸粯?biāo)記釋放的堆空間,會(huì)在任意時(shí)間內(nèi)被其他數(shù)據(jù)使用。所以這對(duì)這個(gè)指針來說是不安全的。
有兩種解決方式:
1、打開僵尸對(duì)象檢查機(jī)制【一但這塊堆空間被標(biāo)記釋放了,那么所有的指針都不能使用這塊空間】
2、將你認(rèn)為可能是指向僵尸堆空間的指針設(shè)置成nil
OC的實(shí)例函數(shù)比較過硬,當(dāng)傳入的第一個(gè)參數(shù),也就是self對(duì)象為nil時(shí),函數(shù)也不會(huì)報(bào)錯(cuò)。
這在.net里會(huì)爆出 【未將對(duì)象引用設(shè)置到對(duì)象實(shí)例】 的錯(cuò)誤的。
ARC:automatic reference counting 自動(dòng)引用計(jì)數(shù)
所有堆空間在新指針引用時(shí)的 retainCount+1 在指針不引用時(shí) retainCount-1。
自動(dòng)維護(hù)引用計(jì)數(shù),并標(biāo)記釋放當(dāng)前堆空間。不需要程序員去關(guān)心。
補(bǔ)充一點(diǎn):
當(dāng)一塊堆空間被標(biāo)記可以刪除之后,即使暫時(shí)沒有新的數(shù)據(jù)填充這塊空間。原來空間的數(shù)據(jù)也不能【復(fù)活】過來重新使用。
eg:
//引用計(jì)數(shù)1
Person* p = [Person new];
//引用計(jì)數(shù)jian-1,為0 觸發(fā)dealloc。標(biāo)記釋放
[p release];//
[p retain];//此塊堆空間已經(jīng)被標(biāo)記釋放,所以對(duì)堆內(nèi)的操作都將無效。數(shù)據(jù)馬上就要被釋放了,還操作個(gè)毛線。