instruments 檢查內(nèi)存泄漏
蘋果原生支持的工具,在開(kāi)發(fā)模式下調(diào)試性能,但無(wú)法和自動(dòng)化外潜,CI進(jìn)行結(jié)合。
- 在xcode中對(duì)當(dāng)前項(xiàng)目執(zhí)行Profile挠唆,打開(kāi)leak模板
- 在leak中選擇對(duì)應(yīng)的設(shè)備和程序处窥,點(diǎn)運(yùn)行,如下圖
在導(dǎo)航欄中可以輸入關(guān)鍵字篩選數(shù)據(jù)玄组,在實(shí)際使用中碧库,我們可以對(duì)一個(gè)頁(yè)面退出后,若該頁(yè)面中相關(guān)內(nèi)存分配還沒(méi)清空巧勤,這時(shí)候就發(fā)生內(nèi)存泄漏了。
AddressSanitizer
使用AddressSanitizer分析內(nèi)存泄漏弄匕。AddressSanitizer開(kāi)啟之后颅悉,在debug過(guò)程中,如果遇到EXC_BAD_ACCESS的問(wèn)題迁匠,Xcode會(huì)自動(dòng)中斷剩瓶,拋出異常。AddressSanitizer的原理是當(dāng)程序創(chuàng)建變量分配一段內(nèi)存時(shí)城丧,將此內(nèi)存后面的一段內(nèi)存也凍結(jié)住延曙,標(biāo)識(shí)為中毒內(nèi)存。當(dāng)程序訪問(wèn)到中毒內(nèi)存時(shí)(越界訪問(wèn))亡哄,就會(huì)拋出異常枝缔,并打印出相應(yīng)log信息。調(diào)試者可以根據(jù)中斷位置和的log信息,識(shí)別bug愿卸。如果變量釋放了灵临,變量所占的內(nèi)存也會(huì)標(biāo)識(shí)為中毒內(nèi)存,這時(shí)候訪問(wèn)這段內(nèi)存同樣會(huì)拋出異常(訪問(wèn)已經(jīng)釋放的對(duì)象)趴荸。
下面制造一個(gè)訪問(wèn)野指針的場(chǎng)景儒溉,array被釋放后,繼續(xù)使用
此時(shí)使用AddressSanitizer发钝,可以看到使用野指針的地方拋出了異常顿涣。
此時(shí)復(fù)制其地址,在XCode中Debug->Debug Workflow->View Memory酝豪,查看該內(nèi)存的使用情況涛碑,可以看到array已經(jīng)被釋放。
NSZombieEnabled
可以定位一些EXC_BAD_ACCESS問(wèn)題寓调,在對(duì)象被錯(cuò)誤釋放的情況下锌唾,可以定位到具體的錯(cuò)誤使用被已被釋放內(nèi)存的對(duì)象。zombie的原理是用生成僵尸對(duì)象來(lái)替換dealloc的實(shí)現(xiàn)夺英,當(dāng)對(duì)象引用計(jì)數(shù)為0的時(shí)候晌涕,將需要dealloc的對(duì)象轉(zhuǎn)化為僵尸對(duì)象。如果之后再給這個(gè)僵尸對(duì)象發(fā)消息痛悯,則拋出異常余黎,并打印出相應(yīng)的信息
具體的設(shè)置,product->edit scheme->argument 下的Environment Variables载萌。添加環(huán)境變量惧财,NSZombieEnabled值為YES即可。在XCode8中在edit scheme中diagnositics中勾選Zombie Objects扭仁。如下圖
同上制造訪問(wèn)野指針的場(chǎng)景垮衷,看到下圖,可以看到有message發(fā)給已經(jīng)被dealloc的對(duì)象乖坠,導(dǎo)致異常搀突。
compiler flags
undefined-trap可以檢測(cè)出程序中的不明確行為,如數(shù)據(jù)溢出等熊泵。如下圖所示當(dāng)數(shù)據(jù)發(fā)生溢出時(shí)仰迁,系統(tǒng)會(huì)拋出異常。
All Exceptions
當(dāng)crash停在main中時(shí)顽分,可能是EXC_CRASH(SIGABRT)或EXC_BAD_ACCESS(SIGBUG/SIGSEGV)導(dǎo)致的徐许。可以在全局加斷點(diǎn)的方式來(lái)查看是哪一行導(dǎo)致了crash卒蘸。
下面制造一個(gè)crash雌隅,如下圖:
此時(shí)運(yùn)行,會(huì)報(bào)錯(cuò),如下圖:
此時(shí)選擇All Exception澄步,就可以看到具體哪行crash了
靜態(tài)檢查
在product中選擇Analyze冰蘑。可以檢查出明顯沒(méi)有釋放的內(nèi)存村缸,主要在兩種場(chǎng)景中使用祠肥,
MRC文件中忘記release或者autorelease,C方式申請(qǐng)內(nèi)存中忘記釋放內(nèi)存梯皿,遺漏了free仇箱。
在關(guān)閉ARC的情況下,打開(kāi)product->Analyze东羹,可以看到下圖剂桥,圖中藍(lán)色標(biāo)記的為有問(wèn)題的地方。
method_exchangeImplementations
使用method_exchangeImplementations接管alloc和dealloc属提,記錄每一次內(nèi)存分配和地址权逗,再遍歷堆區(qū),全局區(qū)冤议,棧區(qū)的指針變量斟薇,進(jìn)行比較,找出沒(méi)有指針變量指向的內(nèi)存地址恕酸。(這個(gè)好像比較高階堪滨,還沒(méi)實(shí)驗(yàn)成功)