一、基本概括
1.什么是內(nèi)存管理?
內(nèi)存管理,是指軟件運(yùn)行時(shí)對(duì)計(jì)算機(jī)內(nèi)存資源的分配和使用的技術(shù)。其最主要的目的是如何高效,快速的分配,并且在適當(dāng)?shù)臅r(shí)候釋放和回收內(nèi)存資源。
2.為什么我們需要內(nèi)存管理?
因?yàn)槭謾C(jī)內(nèi)存大小有限,如果有內(nèi)存分配但是不釋放它,哪怕這塊內(nèi)存已經(jīng)不用了。導(dǎo)致你的應(yīng)用程序占用越來(lái)越多的內(nèi)存,并導(dǎo)致整體性能下降,或者直接在真機(jī)上閃退。因此需要把不必要的內(nèi)存空間給釋放掉。
3.內(nèi)存管理分為:
手動(dòng)內(nèi)存管理(MRC Manual Reference Counting,手動(dòng)引用計(jì)數(shù),我們手動(dòng)管理內(nèi)存)。和自動(dòng)內(nèi)存管理(ARC Automatic Reference Counting,自動(dòng)引用計(jì)數(shù),由xcode,幫我們?nèi)ス芾韮?nèi)存)
在C語(yǔ)言中的內(nèi)存管理,我們手動(dòng)申請(qǐng),手動(dòng)釋放。這樣來(lái)看,我們只需要注意三個(gè)問(wèn)題就好了:
1、申請(qǐng)內(nèi)存,使用完成后需要釋放,如果不釋放會(huì)造成內(nèi)存泄露。
2、不能多次釋放,如果多次釋放,則會(huì)崩潰。
3、不能提前釋放,如果提前釋放,數(shù)據(jù)不安全
C語(yǔ)言的內(nèi)存管理方法:
缺點(diǎn):
在一個(gè)項(xiàng)目里面,成千上萬(wàn)進(jìn)行開發(fā),有一塊存儲(chǔ)空間(堆), 這塊空間里面有一些數(shù)據(jù),這些不單只是我使用,我要用,你也用,他也要用,假如說(shuō)我是用完了這塊數(shù)據(jù),我不可以釋放它,因?yàn)槲也淮_定其他人有沒(méi)有正在使用; 那么出現(xiàn)一個(gè)問(wèn)題:什么時(shí)候才能釋放?
生活映射:
10個(gè)人在森林燒烤, 好不容易把火弄起來(lái),突然有一個(gè)人說(shuō)有事先走, 假如要走的人把火弄滅了, 其它人會(huì)有什么反應(yīng)?
殺了他的心都有,有沒(méi)有辦法,中途有人離開,保證火不會(huì)滅, 當(dāng)所有走了之后, 森林不會(huì)發(fā)生火災(zāi);
解決方法:
計(jì)數(shù)器count記錄人數(shù), 當(dāng)中途有人加入, count++, 中途有人離開, count- -, 當(dāng)count == 0, 把火滅掉;
引用計(jì)數(shù)
對(duì)象: alloc ——》 堆區(qū);
每一個(gè)對(duì)象里面都有一個(gè)引用計(jì)數(shù)器count, 記錄被多少人正在使用;
對(duì)于一塊動(dòng)態(tài)申請(qǐng)的內(nèi)存(對(duì)象),有一個(gè)人(指針)使用,就給這個(gè)內(nèi)存的計(jì)數(shù)器加1,使用完成后,就給這個(gè)計(jì)數(shù)器減1,當(dāng)這個(gè)內(nèi)存的引用計(jì)數(shù)為0了,我們?cè)籴尫潘@樣,上面的問(wèn)題就解決了。OC,就是使用引用計(jì)數(shù)這種方式來(lái)管理內(nèi)存的。
??內(nèi)存管理的黃金法則
1,凡是用alloc,retain,new(或者以new開頭的方法),copy(或者copy開頭的方法),mutableCopy(或者muTableCopy開頭的方法)創(chuàng)建的對(duì)象,都需要用release或者autorelease釋放。
2,誰(shuí)創(chuàng)建誰(shuí)釋放(那個(gè)類創(chuàng)建,那個(gè)類釋放,誰(shuí)寫alloc,誰(shuí)寫release)
4.如何將工程改為MRC

點(diǎn)擊工程—Build settings—> 搜索gar—> 把“ Automatic Reference Counting“ 改為 NO
5.Chatroom實(shí)例
Chatroom.m:
-(void)release
{
[super release];
}
main.m
Chatroom *xiaoming=[[Chatroom alloc]init];
NSLog(@"%ld",xiaoming.retainCount);
Chatroom *xiaogang=xiaoming.retain; //retain 引用計(jì)數(shù)器加1
NSLog(@"%ld",xiaogang.retainCount);
Chatroom *xiaofang=xiaoming.retain;
NSLog(@"%ld",xiaofang.retainCount);
[xiaoming release];
xiaoming=NULL;
[xiaogang release];
xiaogang=NULL;
[xiaofang release];
xiaofang=NULL;
6.分析
1.alloc/new會(huì)導(dǎo)致引用計(jì)數(shù)+1
2.release 會(huì)導(dǎo)致引用計(jì)數(shù)-1
3.對(duì)象在使用完成之后不會(huì)自動(dòng)銷毀,如果不釋放會(huì)內(nèi)存泄露
4.已經(jīng)釋放的數(shù)據(jù)再次使用/釋放(過(guò)度釋放)會(huì)崩潰,通常會(huì)出現(xiàn) Thread 1:EXC_BAD_ACCESS
'(code=EXC_I386_GPFLT)錯(cuò)誤,這是野指針錯(cuò)誤,因?yàn)槟阍L問(wèn)了一塊已經(jīng)不屬于你的內(nèi)存
解決辦法:[obj release]; obj = nil;因?yàn)榻o空對(duì)象發(fā)送消息是不引起錯(cuò)誤的
5.對(duì)象被釋放的時(shí)候會(huì)調(diào)用自己類的delloc方法
7.內(nèi)存管理知識(shí)點(diǎn)
ARC和MRC的關(guān)系
ARC是編譯器特性,不是運(yùn)行時(shí)特性.簡(jiǎn)單說(shuō)就是代碼在編譯的時(shí)候自動(dòng)加入了retain/release/autorelease,原先需要手動(dòng)添加的用來(lái)處理內(nèi)存管理的引用計(jì)數(shù)的代碼可以自動(dòng)地由編譯器完成了.因此ARC和MRC性能是一樣的,有些時(shí)候還能更快,因?yàn)榫幾g器還可以執(zhí)行某些優(yōu)化
8.循環(huán)引用
1.定時(shí)器導(dǎo)致的循環(huán)引用
定時(shí)器在內(nèi)部會(huì)引用self,導(dǎo)致self在釋放的時(shí)候并不會(huì)釋放掉,因此在釋放對(duì)象之前需要先把定時(shí)器給關(guān)閉掉.釋放的代碼[_timer invalidate];_timer = nil;在delloc方法中調(diào)用無(wú)效,一般在viewDidDisappear中關(guān)閉定時(shí)器.
2.代理導(dǎo)致的循環(huán)引用 A,B,C
在A中創(chuàng)建B和C,引用計(jì)數(shù)分別為:A1,B1,A.delegate = B,引用計(jì)數(shù)變?yōu)?A1,B2.如果A釋放,B釋放,那么B變?yōu)锳,導(dǎo)致A.delegate也是1,所以A釋放不掉,B也沒(méi)釋放掉.
解決辦法就是:delegate用assign修飾
3.block導(dǎo)致的循環(huán)引用
9.內(nèi)存優(yōu)化:
1.廣告頁(yè)或者輪播視圖封裝,圖片非常多的時(shí)候,可能會(huì)導(dǎo)致內(nèi)存溢出,優(yōu)化:視圖復(fù)用,圖片壓縮。
2.不要?jiǎng)?chuàng)建太多子視圖
3.NSDateFormmater,NSCalender等對(duì)象,多次使用要復(fù)用