真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

iOS內(nèi)存暴增問(wèn)題追查與使用陷阱-創(chuàng)新互聯(lián)

iOS平臺(tái)的內(nèi)存使用引用計(jì)數(shù)的機(jī)制,并且引入了半自動(dòng)釋放機(jī)制;這種使用上的多樣性,導(dǎo)致開發(fā)者在內(nèi)存使用上非常容易出現(xiàn)內(nèi)存泄漏和內(nèi)存莫名的增長(zhǎng)情況;本文會(huì)介紹iOS平臺(tái)的內(nèi)存使用原則與使用陷阱;深度剖析autorelease機(jī)制;低內(nèi)存報(bào)警后的處理流程;并結(jié)合自身實(shí)例介紹內(nèi)存暴增的問(wèn)題追查記錄以及相關(guān)工具的使用情況;

目前創(chuàng)新互聯(lián)建站已為超過(guò)千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)頁(yè)空間、網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、疊彩網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

TAG

內(nèi)存暴增,內(nèi)存泄漏,autorelease;內(nèi)存報(bào)警;

iOS平臺(tái)內(nèi)存常見問(wèn)題

作為iOS平臺(tái)的開發(fā)者,是否曾經(jīng)為內(nèi)存問(wèn)題而苦惱過(guò)??jī)?nèi)存莫名的持續(xù)增長(zhǎng),程序莫名的crash,難以發(fā)現(xiàn)的內(nèi)存泄漏,這些都是iOS平臺(tái)內(nèi)存相關(guān)的常見問(wèn)題;本文將會(huì)詳細(xì)介紹iOS平臺(tái)的內(nèi)存管理機(jī)制,autorelease機(jī)制和內(nèi)存的使用陷阱,這些將會(huì)解決iOS平臺(tái)內(nèi)存上的大部分問(wèn)題,提高了程序的穩(wěn)定性;

1 iOS平臺(tái)內(nèi)存管理介紹

iOS平臺(tái)的內(nèi)存管理采用引用計(jì)數(shù)的機(jī)制;當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí)使用alloc或者allWithZone方法時(shí),引用計(jì)數(shù)就會(huì)+1;當(dāng)釋放對(duì)象使用release方法時(shí),引用計(jì)數(shù)就是-1;這就意味著每一個(gè)對(duì)象都會(huì)跟蹤有多少其他對(duì)象引用它,一旦引用計(jì)數(shù)為0,該對(duì)象的內(nèi)存就會(huì)被釋放掉;另外,iOS也提供了一種延時(shí)釋放的機(jī)制AutoRelease,以這種方式申請(qǐng)的內(nèi)存,開發(fā)者無(wú)需手動(dòng)釋放,系統(tǒng)會(huì)在某一時(shí)機(jī)釋放該內(nèi)存;由于iOS平臺(tái)的這種內(nèi)存管理的多樣性,導(dǎo)致開發(fā)者在內(nèi)存使用上很容易出現(xiàn)內(nèi)存泄漏或者程序莫名崩潰的情況,本文會(huì)詳細(xì)介紹iOS平臺(tái)內(nèi)存的使用規(guī)范與技巧以及如何利用工具避免或者發(fā)現(xiàn)問(wèn)題;

下圖是內(nèi)存從申請(qǐng)到釋放的一個(gè)完整示例:

iOS內(nèi)存暴增問(wèn)題追查與使用陷阱 iOS內(nèi)存暴增問(wèn)題追查與使用陷阱

2 iOS平臺(tái)內(nèi)存使用原則

2.1 對(duì)象的所有權(quán)與銷毀

2.1.1 誰(shuí)創(chuàng)建,誰(shuí)釋放;

如果是以alloc,new或者copy,mutableCopy創(chuàng)建的對(duì)象,則必須調(diào)用release或者autorelease方法釋放內(nèi)存;

如果沒(méi)有釋放,則導(dǎo)致內(nèi)存泄漏!

2.1.2 誰(shuí)retain,誰(shuí)釋放;

如果對(duì)一個(gè)對(duì)象發(fā)送 retain消息,其引用計(jì)數(shù)會(huì)+1,則使用完必須發(fā)送release或者autorelease方法釋放內(nèi)存或恢復(fù)引用計(jì)數(shù);

如果沒(méi)有釋放,則導(dǎo)致內(nèi)存泄漏!

2.1.3 沒(méi)創(chuàng)建且沒(méi)retain,別釋放;

不要釋放那些不是自己alloc或者retain的對(duì)象,否則程序會(huì)crash

不要釋放autorelease的對(duì)象,否則程序會(huì)crash;

2.2 對(duì)象的深拷貝與淺拷貝

一般來(lái)說(shuō),復(fù)制一個(gè)對(duì)象包括創(chuàng)建一個(gè)新的實(shí)例,并以原始對(duì)象中的值初始化這個(gè)新的實(shí)例。復(fù)制非指針型實(shí)例變量的值很簡(jiǎn)單,比如布爾,整數(shù)和浮點(diǎn)數(shù)。復(fù)制指針型實(shí)例變量有兩種方法。一種方法稱為淺拷貝,即將原始對(duì)象的指針值復(fù)制到副本中。因此,原始對(duì)象和副本共享引用數(shù)據(jù)。另一種方法稱為深拷貝,即復(fù)制指針?biāo)玫臄?shù)據(jù),并將其賦給副本的實(shí)例變量。

2.2.1 深拷貝

深拷貝的流程是 先創(chuàng)建一個(gè)的對(duì)象且引用計(jì)數(shù)為1,并用舊對(duì)象的值初始化這個(gè)新對(duì)象;

ClassA* objA = [[ClassA alloc] init];

ClassA* objB = [objA copy];

objB是一個(gè)新對(duì)象,引用計(jì)數(shù)為1,且objB的數(shù)據(jù)等同objA的數(shù)據(jù);

注意: objB需要釋放,否則會(huì)引起內(nèi)存泄漏!

2.2.2 淺拷貝

淺拷貝的流程是,無(wú)需引入新的對(duì)象,把原有對(duì)象的引用計(jì)數(shù)+1即可

ClassA* objA = [[ClassA alloc] init];

ClassA* objB = [objA retain];

注意: objB需要釋放,恢復(fù)objA的引用計(jì)數(shù),否則會(huì)引起內(nèi)存泄漏!

2.3對(duì)象的存取方法

2.3.1 屬性聲明和實(shí)現(xiàn)

變量聲明的常用屬性類型包括readonly,assign,retain和copy;且系統(tǒng)會(huì)自動(dòng)為聲明了屬性的變量生成set和get函數(shù);

readonly屬性: 只能讀,不能寫;

assign屬性: 是默認(rèn)屬性,直接賦值,沒(méi)有任何保留與釋放問(wèn)題;

retain屬性: 會(huì)增加原有對(duì)象的引用計(jì)數(shù)并且在賦值前會(huì)釋放原有對(duì)象,然后在進(jìn)行賦值;

copy屬性:  會(huì)復(fù)制原有對(duì)象,并在賦值前釋放原有對(duì)象,然后在進(jìn)行賦值;

2.3.2 使用屬性聲明可能帶來(lái)的隱患

當(dāng)一個(gè)非指針變量使用retain(或者copy)這個(gè)屬性時(shí),盡量不要顯性的release這個(gè)變量;直接給這個(gè)變量置空即可;否則容易產(chǎn)生過(guò)度釋放,導(dǎo)致程序crash;例如:

ClassA類的strName是NSString* 類型的變量且聲明的屬性為retain;

ClassA.strName = nil;

[ClassA.strName release];

Assign這個(gè)屬性一般是非指針變量(布爾類型,×××等)時(shí)用這個(gè)類型;屬于直接賦值型,不需要考慮內(nèi)存的保留與釋放;

如果一個(gè)指針類型的變量使用assign類型的屬性,有可能引用已經(jīng)釋放的變量;導(dǎo)致程序crash; 例如:

ClassB* obj =[[[ClassB alloc] init] autorelease];

……

ClassA.strName = obj;

后續(xù)在使用ClassA.strName的時(shí)候,因?yàn)閛bj是autorelease的,可能obj的內(nèi)存已經(jīng)被回收;導(dǎo)致引用無(wú)效內(nèi)存,程序crash;

3iOS平臺(tái)AutoRelease機(jī)制

3.1 自動(dòng)釋放池的常見問(wèn)題

大家在開發(fā)iOS程序的時(shí)候,是否遇到過(guò)在列表滑動(dòng)的情況內(nèi)存莫名的增長(zhǎng),頻繁訪問(wèn)圖片的時(shí)候內(nèi)存莫名的增長(zhǎng),頻繁的打開和關(guān)閉數(shù)據(jù)庫(kù)的時(shí)候內(nèi)存莫名的增長(zhǎng)…… 這些都是拜iOS的autorelease機(jī)制所賜;具體分析如下:

1: 滑動(dòng)列表的時(shí)候,內(nèi)存出現(xiàn)莫名的增長(zhǎng),原因可能有如下可能:

1:沒(méi)有使用UITableView的reuse機(jī)制;導(dǎo)致每顯示一個(gè)cell都用autorelease的方式重新alloc一次; 導(dǎo)致cell的內(nèi)存不斷的增加;

2:每個(gè)cell會(huì)顯示一個(gè)單獨(dú)的UIView, 在UIView發(fā)生內(nèi)存泄漏,導(dǎo)致cell的內(nèi)存不斷增長(zhǎng);

2: 頻繁訪問(wèn)圖片的時(shí)候,內(nèi)存莫名的增長(zhǎng);

頻繁的訪問(wèn)網(wǎng)絡(luò)圖片,導(dǎo)致iOS內(nèi)部API,會(huì)不斷的分配autorelease方式的buffer來(lái)處理圖片的解碼與顯示;利用圖片cache可以緩解一下此問(wèn)題;

3: 頻繁打開和關(guān)閉SQLite,導(dǎo)致內(nèi)存不斷的增長(zhǎng);

在進(jìn)行SQLite頻繁打開和關(guān)閉操作,而且讀寫的數(shù)據(jù)buffer較大,那么SQLite在每次打開與關(guān)閉的時(shí)候,都會(huì)利用autorelease的方式分配51K的內(nèi)存;如果訪問(wèn)次數(shù)很多,內(nèi)存馬上就會(huì)頂?shù)綆资?,甚至上百兆?所以針對(duì)頻繁的讀寫數(shù)據(jù)庫(kù)且數(shù)據(jù)buffer較大的情況, 可以設(shè)置SQLite的長(zhǎng)連接方式;避免頻繁的打開和關(guān)閉數(shù)據(jù)庫(kù);

3.2 自動(dòng)釋放池的概念

NSAutoreleasePool內(nèi)部包含一個(gè)數(shù)組(NSMutableArray),用來(lái)保存聲名為autorelease的所有對(duì)象。如果一個(gè)對(duì)象聲明為autorelease,系統(tǒng)所做的工作就是把這個(gè)對(duì)象加入到這個(gè)數(shù)組中去。

ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1,把此對(duì)象加入autorelease pool中

NSAutoreleasePool自身在銷毀的時(shí)候,會(huì)遍歷一遍這個(gè)數(shù)組,release數(shù)組中的每個(gè)成員。如果此時(shí)數(shù)組中成員的retain count為1,那么release之后,retain count為0,對(duì)象正式被銷毀。如果此時(shí)數(shù)組中成員的retain count大于1,那么release之后,retain count大于0,此對(duì)象依然沒(méi)有被銷毀,內(nèi)存泄露。

3.3 自動(dòng)釋放池的作用域與嵌套

AutoreleasePool是可以嵌套使用的!
池是被嵌套的,嵌套的結(jié)果是個(gè)棧,同一線程只有當(dāng)前棧頂pool實(shí)例是可用的: iOS內(nèi)存暴增問(wèn)題追查與使用陷阱

當(dāng)短生命周期內(nèi),比如一個(gè)循環(huán)中,會(huì)產(chǎn)生大量的臨時(shí)內(nèi)存,可以創(chuàng)建一個(gè)臨時(shí)的autorelease pool,這樣可以達(dá)到快速回收內(nèi)存的目的;

3.4 自動(dòng)施放池的手動(dòng)創(chuàng)建與自動(dòng)創(chuàng)建

3.4.1 需要手動(dòng)創(chuàng)建自動(dòng)釋放池

●如果你正在編寫一個(gè)不是基于Application Kit的程序,比如命令行工具,則沒(méi)有對(duì)自動(dòng)釋放池的內(nèi)置支持;你必須自己創(chuàng)建它們。

●如果你生成了一個(gè)從屬線程,則一旦該線程開始執(zhí)行,你必須立即創(chuàng)建你自己的自動(dòng)釋放池;否則,你將會(huì)泄漏對(duì)象。

●如果你編寫了一個(gè)循環(huán),其中創(chuàng)建了許多臨時(shí)對(duì)象,你可以在循環(huán)內(nèi)部創(chuàng)建一個(gè)自動(dòng)釋放池,以便在下次迭代之前銷毀這些對(duì)象。這可以幫助減少應(yīng)用程序的大內(nèi)存占用量。

3.4.2 系統(tǒng)自動(dòng)創(chuàng)建自動(dòng)釋放池

Application Kit會(huì)在一個(gè)事件周期(或事件循環(huán)迭代)的開端—比如鼠標(biāo)按下事件—自動(dòng)創(chuàng)建一個(gè)自動(dòng)釋放池,并且在事件周期的結(jié)尾釋放它.

4 iOS平臺(tái)內(nèi)存使用陷阱

4.1 重復(fù)釋放

在前文已經(jīng)提到,不要釋放不是自己創(chuàng)建的對(duì)象;

釋放自己的autorelease對(duì)象,app會(huì)crash;

釋放系統(tǒng)的autorelease對(duì)象,app會(huì)crash;

4.2 循環(huán)引用 iOS內(nèi)存暴增問(wèn)題追查與使用陷阱

循環(huán)引用,容易產(chǎn)生野引用,內(nèi)存無(wú)法回收,最終導(dǎo)致內(nèi)存泄漏!可以通過(guò)弱引用的方式來(lái)打破循環(huán)引用鏈;所謂的弱引用就是不需要retain,直接賦值的方式,這樣的話,可以避免循環(huán)引用的問(wèn)題,但是需要注意的是,避免重復(fù)釋放的問(wèn)題;

5 iOS平臺(tái)內(nèi)存報(bào)警機(jī)制

由于iOS平臺(tái)的內(nèi)存管理機(jī)制,不支持虛擬內(nèi)存,所以在內(nèi)存不足的情況,不會(huì)去Ram上創(chuàng)建虛擬內(nèi)存;所以一旦出現(xiàn)內(nèi)存不足的情況,iOS平臺(tái)會(huì)通知所有已經(jīng)運(yùn)行的app,不論是前臺(tái)app還是后臺(tái)掛起的app,都會(huì)收到 memory warning的notice;一旦app收到memory warning的notice,就應(yīng)該回收占用內(nèi)存較大的變量;

5.1 內(nèi)存報(bào)警處理流程

1: app收到系統(tǒng)發(fā)過(guò)來(lái)的memory warning的notice;

2: app釋放占用較大的內(nèi)存;

3: 系統(tǒng)回收此app所創(chuàng)建的autorelease的對(duì)象;

4: app返回到已經(jīng)打開的頁(yè)面時(shí),系統(tǒng)重新調(diào)用viewdidload方法,view重新加載頁(yè)面數(shù)據(jù);重新顯示;

5.2 內(nèi)存報(bào)警測(cè)試方法

在Simulate上可以模擬低內(nèi)存報(bào)警消息;

iOS模擬器 -> 硬件 -> 模擬內(nèi)存警告;

開發(fā)者可以在模擬器上來(lái)模擬手機(jī)上的低內(nèi)存報(bào)警情況,可以避免由于低內(nèi)存報(bào)警引出的app的莫名crash問(wèn)題;

6 iOS平臺(tái)內(nèi)存檢查工具

6.1 編譯和分析工具Analyze

iOS的分析工具可以發(fā)現(xiàn)編譯中的warning,內(nèi)存泄漏隱患,甚至還可以檢查出logic上的問(wèn)題;所以在自測(cè)階段一定要解決Analyze發(fā)現(xiàn)的問(wèn)題,可以避免出現(xiàn)嚴(yán)重的bug;

內(nèi)存泄漏隱患提示

Potential Leak of an object allocated on line ……

數(shù)據(jù)賦值隱患提示

The left operand of …… is a garbage value;

對(duì)象引用隱患提示

Reference-Counted object is used after it is released;

以上提示均比較嚴(yán)重,可能會(huì)引起嚴(yán)重問(wèn)題,需要開發(fā)者密切關(guān)注!

6.2 內(nèi)存檢測(cè)工具

6.2.1 內(nèi)存泄漏檢測(cè)工具—Leak

Leak工具可以很容易的統(tǒng)計(jì)所有內(nèi)存泄漏的點(diǎn),而且還可以顯示在那個(gè)文件,哪行代碼有內(nèi)存泄漏,這樣定位問(wèn)題比較容易,也比較方面;但是Leak在統(tǒng)計(jì)內(nèi)存泄漏的時(shí)候會(huì)把a(bǔ)utorelease方式的內(nèi)存也統(tǒng)計(jì)進(jìn)來(lái);所以我們?cè)诓檎覂?nèi)存泄漏情況的時(shí)候,可以autorelease的情況忽略掉;

Leak工具:

iOS內(nèi)存暴增問(wèn)題追查與使用陷阱 通過(guò)Leak工具可以很快發(fā)現(xiàn)代碼中的內(nèi)存泄漏,通過(guò)工具也可以很快找到發(fā)生內(nèi)存泄漏的代碼段:

iOS內(nèi)存暴增問(wèn)題追查與使用陷阱

6.2.2 內(nèi)存猛增檢測(cè)工具—Allocations

Allocations工具可以很容易的列出所有分配內(nèi)存的點(diǎn),這樣我們可以按照分配內(nèi)存大小來(lái)進(jìn)行排序,這樣可以很容易的發(fā)現(xiàn)哪些點(diǎn)分配的內(nèi)存最多,而且是持續(xù)分配,這樣我們來(lái)針對(duì)性的分析這些持續(xù)分配較大內(nèi)存的地方;

iOS內(nèi)存暴增問(wèn)題追查與使用陷阱 此工具會(huì)顯示出所有申請(qǐng)內(nèi)存的地方,并統(tǒng)計(jì)申請(qǐng)的次數(shù)和大??;從這個(gè)列表中可以找出內(nèi)存申請(qǐng)次數(shù)最多且申請(qǐng)內(nèi)存大的語(yǔ)句;從而分析出哪些地方使用的內(nèi)存最多,進(jìn)而可以優(yōu)化和改進(jìn);iOS內(nèi)存暴增問(wèn)題追查與使用陷阱

上圖是按照申請(qǐng)內(nèi)存多少來(lái)排序的,可以方便的了解哪些代碼申請(qǐng)的內(nèi)存多

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。


名稱欄目:iOS內(nèi)存暴增問(wèn)題追查與使用陷阱-創(chuàng)新互聯(lián)
文章來(lái)源:http://weahome.cn/article/dddsgh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部