溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

OC的內(nèi)存管理

發(fā)布時(shí)間:2020-06-28 10:16:05 來源:網(wǎng)絡(luò) 閱讀:684 作者:飛奔的土豆 欄目:開發(fā)技術(shù)

1.內(nèi)存泄露

一般我們常說的內(nèi)存泄漏是指堆內(nèi)存的泄漏。堆內(nèi)存是指程序從堆中分配的,大小任意的(內(nèi)存塊的大小可以在程序運(yùn)行期決定),使用完后必須顯式釋放的內(nèi)存。應(yīng)用程序一般使用malloc,callocrealloc等函數(shù)(C++中使用new操作符)從堆中分配到一塊內(nèi)存,使用完后,程序必須負(fù)責(zé)相應(yīng)的調(diào)用freedelete釋放該內(nèi)存塊,否則,這塊內(nèi)存就不能被再次使用,我們就說這塊內(nèi)存泄漏了。

2. 內(nèi)存管理

堆中的內(nèi)存都是手動(dòng)開辟和手動(dòng)釋放的。因此我們要時(shí)刻統(tǒng)計(jì)堆的指針有哪些是指向同一個(gè)的。再釋放時(shí),確認(rèn)所有指向這個(gè)堆的指針,都已經(jīng)用完了,不再使用。但這個(gè)存在先天的不足,畢竟程序員在統(tǒng)計(jì)指針是否用完時(shí),受到多方面的影響而不能正確統(tǒng)計(jì),程序在聯(lián)合開發(fā)的時(shí)候,指向同一個(gè)的堆的指針就很難統(tǒng)計(jì),因此必須有一個(gè)合理的方法來管理內(nèi)存。

3. 理解內(nèi)存管理到底干了什么?

OC中的內(nèi)存管理實(shí)際上就是一種PV操作,就是對(duì)計(jì)數(shù)器的加減操作。基類NSObject存在一個(gè)計(jì)數(shù)器retainCount,并會(huì)被子類所繼承。alloc創(chuàng)建對(duì)象時(shí),計(jì)數(shù)器+1,retain純粹的計(jì)數(shù)器+1release將計(jì)數(shù)器減1,不是真的free掉一個(gè)對(duì)象,release時(shí)本著個(gè)人顧個(gè)人的原則。

4. release原則(黃金法則)

當(dāng)我們用allocretainnew,copy,mutablecopy這些函數(shù)創(chuàng)建地址付給指針時(shí),需要用release或者autorelease釋放。釋放的時(shí)候,每個(gè)指針誰創(chuàng)建的誰釋放,不能去釋放別人創(chuàng)建的指針。

5. 成員變量為對(duì)象的set函數(shù)

一個(gè)類的成員變量為另一個(gè)類的對(duì)象時(shí),為了考慮內(nèi)存管理,set函數(shù)的一般寫法,以Car類擁有Engine對(duì)象作為成員變量為例:

-(void)setEngine:(Engine *)newengine

{

if(engine!=newengine){ //判斷是否自我賦值

[engine release]; //若為對(duì)象賦新值,先release舊的

engine=[newEngine retain]; //賦新值且retain一下計(jì)數(shù)器+1

}

return;

}

 

這個(gè)set函數(shù)充分的考慮到了,自我賦值和對(duì)象取新值的情況,engine為空時(shí),[engine release]執(zhí)行一次,但不會(huì)產(chǎn)生效果,所以不會(huì)出現(xiàn)錯(cuò)誤。因?yàn)?/span>OC在創(chuàng)建對(duì)象時(shí),成員變量默認(rèn)為nil,[nil release]能夠執(zhí)行,但是沒有效果,即不會(huì)對(duì)計(jì)數(shù)器產(chǎn)生影響。但是存在一個(gè)問題,就是賦新值后retain后,使用完成后會(huì)發(fā)現(xiàn)無法對(duì)其release,因?yàn)?/span>car類對(duì)象一直使用著這個(gè)值,car對(duì)象銷毀,才執(zhí)行retain一次,減少engine計(jì)數(shù)器一次。因此必須重寫Car類的dealloc函數(shù),在car對(duì)象釋放時(shí),release一下engine,以對(duì)應(yīng)set函數(shù)中的retain,滿足黃金法則。

重寫的dealloc函數(shù)為:

-(void)dealloc //car的對(duì)象釋放時(shí),自動(dòng)調(diào)用,類似析構(gòu)函數(shù)

{

[engine release]; //self.engine=nil;作用相同(調(diào)用set函數(shù))

[surper dealloc]; //模擬C++析構(gòu)時(shí),調(diào)用父類的析構(gòu)函數(shù)

return;

}

6. 特殊成員變量的點(diǎn)語法

不同于普通變量,setget函數(shù)封裝應(yīng)為:

@property (retain) Engine * engine;

@synthesize engine;

這樣就不用麻煩的自己書寫set函數(shù)了。一個(gè)類的成員是另一個(gè)類時(shí),此時(shí) set函數(shù)會(huì)與以前的普通成員邊量set函數(shù)大有不同,set函數(shù)書寫為內(nèi)存 管路版本使用時(shí),一定要重寫dealloc函數(shù),處理成員對(duì)象的最后一次release。

7. atuoreleaseatuoreleasepool

新版的自動(dòng)釋放池寫法為;

@autoreleasepool

{

}

釋放池作為一個(gè)關(guān)鍵字存在,老版本的釋放池的書寫更易于理解,寫法如下:

NSAutorelease *pool = [[NSAutoreleasePool alloc]init];

…………

[pool release];

可以將pool看為一個(gè)數(shù)組,將relase的對(duì)象裝在這個(gè)數(shù)組中,等到釋放池 釋放的時(shí)候,才把池中的對(duì)象全部執(zhí)行一次release。

8. 以對(duì)象dog為例,使用自動(dòng)釋放池release

[dog autorelease]; //自動(dòng)釋放 延遲釋放

這里是將dog地址添加到pool中,pool執(zhí)行release時(shí),才把池中的對(duì)象全 部執(zhí)行一次release。在這之前,計(jì)數(shù)器并沒有真正的減一,pool釋放的時(shí) dog的計(jì)數(shù)器才會(huì)真正的減一。

9. 不到萬不得已的時(shí)候,千萬不要用autoreleasepool

IOS中每一個(gè)觸發(fā)周期,系統(tǒng)都會(huì)自動(dòng)創(chuàng)建一個(gè)自動(dòng)釋放池,在周期結(jié)束時(shí), 就會(huì)釋放這個(gè)pool。autorelease自動(dòng)匹配最近的一個(gè)pool,我們并不能控 制其在我們想要釋放的時(shí)候才釋放。

+函數(shù)創(chuàng)建一個(gè)對(duì)象時(shí),并不能確定何時(shí)釋放對(duì)象,因此我們?cè)?/span>pool釋放時(shí), 再釋放這個(gè)對(duì)象,避免錯(cuò)誤。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI