使用Xcode Instruments 定位iOS應(yīng)用的Memory Leaks

了解:在蘋果沒有出ARC(自動(dòng)內(nèi)存管理機(jī)制)時(shí),iOS開發(fā)攻城獅幾乎有一半的開發(fā)時(shí)間都消耗在怎么管理內(nèi)存上后來蘋果人性化推出了ARC,雖然在很大程度上幫助我們開發(fā)者節(jié)省了精力和時(shí)間。但是我們?cè)陂_發(fā)過程中,由于種種原因,還是會(huì)出現(xiàn)內(nèi)存泄漏的問題。
內(nèi)存泄漏是一個(gè)很嚴(yán)重的問題,我們先了解一下xcode7自帶的Instruments中的Leaks如何檢測(cè)我們的程序中內(nèi)存泄漏以及定位內(nèi)存泄漏代碼(Leaks分析內(nèi)存泄漏并不能把所有的內(nèi)存泄漏問題查出來,有的內(nèi)存泄漏時(shí)在運(yùn)行時(shí),用戶操作時(shí)才會(huì)產(chǎn)生的)


簡(jiǎn)介內(nèi)存管理:

  • Object-C有3種內(nèi)存管理方式,他們分別是
    • MRR (Manual Retain Release, 手動(dòng)保持釋放)
    • ARC (Automatic Reference Counting,自動(dòng)引用計(jì)數(shù))
    • GC (Garbage Collection,垃圾收集)
  • 1> MRR
    • ① 也稱為 MRC (Manual Reference Counting,手動(dòng)引用計(jì)數(shù))
    • ② 由程序員自己負(fù)責(zé)管理對(duì)象生命周期,負(fù)責(zé)對(duì)象的創(chuàng)建和銷毀
  • 2> ARC
    • ① 采用和MRR一樣的內(nèi)存引用計(jì)數(shù)管理方式
    • ② 在編譯時(shí)會(huì)在適合的位置插入對(duì)象內(nèi)存釋放,(如 release, autorelease, 和 retain 等)
    • ③ 程序員不需要關(guān)心對(duì)象釋放的問題,蘋果推薦在新項(xiàng)目中使用ARC,但在iOS5之前的項(xiàng)目中不能采用ARC
  • 3> GC
    • ① 在Objective_C2.0之后,內(nèi)存管理出現(xiàn)了類似于Java和C#的內(nèi)存垃圾收集技術(shù),但是垃圾收集與ARC一直運(yùn)行,垃圾收集時(shí)后臺(tái)有一個(gè)線程負(fù)責(zé)檢查已經(jīng)不在使用的對(duì)象,然后釋放,
    • ② 由于后臺(tái)有一個(gè)線程一直運(yùn)行,會(huì)嚴(yán)重影響性能,這也是java和C#程序的運(yùn)行速度無法超越C++的主要原因
    • ③ GC技術(shù)不能應(yīng)用于iOS開發(fā),只能使用與Mac OS X開發(fā)

內(nèi)存泄漏

  • 內(nèi)存泄漏指當(dāng)一個(gè)對(duì)象或變量在使用完成后沒有釋放掉,這個(gè)對(duì)象一直占用這部分的內(nèi)存,直到應(yīng)用停止
  • 這種沒有釋放掉的對(duì)象多了內(nèi)存就會(huì)耗盡,其他應(yīng)用就無法運(yùn)行
  • 內(nèi)存泄漏在C++,C和Objective-C的MRR中是比較普遍的問題
  • 從理論上講,內(nèi)存泄漏是由對(duì)象或者變量沒有釋放引起的,但實(shí)踐證明并非所有的未釋放的對(duì)象或變量都會(huì)導(dǎo)致內(nèi)存泄漏,這與硬件環(huán)境和操作系統(tǒng)、系統(tǒng)環(huán)境有關(guān)
  • 內(nèi)存泄漏導(dǎo)致我們軟件在運(yùn)行過程中占用越來越多的內(nèi)存,占有資源卻又得不到及時(shí)清理,會(huì)導(dǎo)致我們程序效率越來越低,反應(yīng)慢,會(huì)影響我們用戶體驗(yàn),失去市場(chǎng)的競(jìng)爭(zhēng)能力

iOS中查找漏點(diǎn)的工具

  • 在xcode中,共提供兩種工具幫助查找泄漏點(diǎn),
    • 1> Analyze
      • 學(xué)名:靜態(tài)分析工具
      • 查找:可以通過 product -> Analyze 菜單項(xiàng)啟動(dòng)
      • 快捷鍵 CMD + Shift + b
      • Analyze主要分析一下四種問題
        • 邏輯錯(cuò)誤:訪問空指針或?yàn)槌跏蓟淖兞康龋?/li>
        • 內(nèi)存管理錯(cuò)誤:如內(nèi)存泄漏等;
        • 聲明錯(cuò)誤:從未使用過的變量
        • Api調(diào)用錯(cuò)誤:未包含使用庫(kù)和框架
    • 2> Instruments
      • 學(xué)名:動(dòng)態(tài)分析工具
      • 查找:product -> profile 菜單項(xiàng)啟動(dòng)
      • 快捷鍵 CMD + i
      • 簡(jiǎn)介:它有很多跟跟蹤模塊可以動(dòng)態(tài)分析和跟蹤內(nèi)存,CPU和文件系統(tǒng)

兩種工具查找漏點(diǎn)版本的介紹

  • 1> 結(jié)合使用-思路分析:
    • 先使用Analyze靜態(tài)分析查找可疑泄漏點(diǎn),在用Instruments動(dòng)態(tài)分析中的Leaks和Allocations跟蹤板塊進(jìn)行動(dòng)態(tài)跟蹤分析,確認(rèn)這些點(diǎn)是否泄漏,或者是否存有新的泄漏點(diǎn)出現(xiàn)等
  • 2>使用 靜態(tài)檢測(cè)內(nèi)存泄漏問題 Analyze
  • 在Analyze靜態(tài)分析結(jié)果中,凡是有圖標(biāo)出現(xiàn)的行都是工具發(fā)現(xiàn)的疑似泄漏點(diǎn)


    疑似泄漏點(diǎn)所在行.png
  • 點(diǎn)擊疑似泄漏點(diǎn)行末尾的分叉圖標(biāo),會(huì)展開分析結(jié)果


    展開分析結(jié)果.png
  • 檢測(cè)完成時(shí)的效果圖如下:


    分析效果圖.png
  • 小結(jié):
    • 這里使用Analyze靜態(tài)分析查找出來的泄漏點(diǎn),稱之為“可疑泄漏點(diǎn)”,之所以稱之為“可疑泄漏點(diǎn)”,是因?yàn)檫@些點(diǎn)未必一定泄漏,確認(rèn)這些點(diǎn)是否泄漏,還要通過Instruments動(dòng)態(tài)分析工具的Leaks和Allocations跟蹤模版,Analyze靜態(tài)分析只是一個(gè)理論上的預(yù)測(cè)過程
  • 3> 動(dòng)態(tài)監(jiān)測(cè)Instruments的Leaks
    • 1)CMD + i 打開
      CMD打開.png
    • 2)打開頁(yè)面的介紹:


      界面介紹.png
    • 在instruments中,雖然選擇了Leaks模版,但默認(rèn)情況下也會(huì)添加Allocations模版,基本上凡是內(nèi)存分析都會(huì)使用Allocations模版,它可以監(jiān)控內(nèi)存分布情況
      • a. 選中Allocations模版,(圖1區(qū)域),右邊的3區(qū)域會(huì)顯示隨著十斤啊的變化內(nèi)存使用的折線圖,同時(shí)在4區(qū)域會(huì)顯示內(nèi)存使用的詳細(xì)信息,以及對(duì)象分配情況
      • b. 點(diǎn)擊Leaks模版(圖中2區(qū)域)可以查看內(nèi)存泄漏情況。如果在3區(qū)域中有紅x出現(xiàn),則有內(nèi)存泄漏,4區(qū)域則會(huì)顯示泄漏的對(duì)象
    • 3)打開Leaks進(jìn)行監(jiān)測(cè):
    • 點(diǎn)擊泄漏對(duì)象可以在(下圖)看到它們的內(nèi)存地址,占用字節(jié),所屬框架和響應(yīng)方法等信息,打開擴(kuò)展視圖,可以看到右邊的跟蹤堆棧信息


      leaks進(jìn)行監(jiān)測(cè).png
    • 4)監(jiān)測(cè)結(jié)果的分析:


      監(jiān)測(cè)結(jié)果的分析.png
    • 5)Allocations—內(nèi)存分配版本的介紹
    • Allocations是監(jiān)測(cè)程序運(yùn)行過程中 內(nèi)存分配情況的,也需要同時(shí)運(yùn)行著程序。界面情況如下:


      Allocations.png

      Allocations .jpg
    • 雙擊某一個(gè)方法,同樣會(huì)跳轉(zhuǎn)到代碼中,會(huì)有每一句代碼對(duì)應(yīng)的內(nèi)存分配情況,根據(jù)這些信息,可以對(duì)程序里不同代碼的內(nèi)存占用情況有一些認(rèn)識(shí),并進(jìn)行針對(duì)性優(yōu)化

具體使用

  • 1>. Allocations紀(jì)錄了內(nèi)存分配,用來優(yōu)化內(nèi)存使用的
  • 2>. Leaks用來分析內(nèi)存泄漏。ARC中引起的內(nèi)存泄漏原因就是引用環(huán)

  • 第一步:先選擇Leaks和Leaks by Backtrace.這里可以看到那些對(duì)象內(nèi)訓(xùn)泄漏了,泄漏了多少,這個(gè)就是簡(jiǎn)單看看,沒有太多調(diào)試意義
    監(jiān)測(cè)內(nèi)存泄漏多少.png
  • 第二步:然后看看Call Tree,因?yàn)镃all Tree會(huì)給我們大概的位置,有時(shí)候會(huì)給我們精確的位置,不過要看運(yùn)氣了。
    然后,再右面選擇Invert Call Tree和Hide System Library
    Call Tree.png
  • 雙擊上圖中的任意一行,就會(huì)跳到代碼處內(nèi)存泄漏的地方(事實(shí)上,到這步,很多內(nèi)存泄漏的問題都會(huì)被發(fā)現(xiàn)),當(dāng)然也有一些泄漏還是看不出來的
  • 第三步
  • 然后我們選擇對(duì)ARC調(diào)試很有用的一部分Circles & Roots,通過這個(gè)我們可以看到詳細(xì)的ARC引用計(jì)數(shù)過程。然后,我們看到如下圖


    CirCles & Roots.png
    • 小的紅色矩形點(diǎn)擊可以看出引用計(jì)數(shù)的詳細(xì)信息(ARC就是自動(dòng)引用計(jì)數(shù),計(jì)數(shù)為0,則對(duì)象會(huì)被釋放)
    • 大的紅色矩形可以描繪對(duì)象引用環(huán)的圖,這里如果是我們自己的東西,就能看出來哥哥對(duì)象的引用
  • 如果這里沒有引用環(huán)的圖,首先我們找一下我們自定義的對(duì)象,正常完成任務(wù)這個(gè)對(duì)像就應(yīng)該釋放了,為了確認(rèn)這個(gè)對(duì)象有釋放,可以重寫dealloc方法,在此方法中l(wèi)og釋放信號(hào),看看是否被釋放
  • 如果這里就是沒有釋放,我們可以點(diǎn)擊這里對(duì)象后的箭頭詳細(xì)查看下,這個(gè)對(duì)象的引用計(jì)數(shù)變化如圖
    • All 代表所有的引用計(jì)數(shù)變化
    • Unpaired表示那些未成對(duì)的變化·· (成對(duì)就是Leaks識(shí)別出了對(duì)應(yīng)的+1,-1)
    • By Group會(huì)把相應(yīng)的變化分成一組
    • ByTime會(huì)按照順序列出引用計(jì)數(shù)變化


      詳細(xì)信息.png

  • 總結(jié):其實(shí)大多數(shù)問題在雙擊上文的代碼部分就可以解決了,少數(shù)問題需要詳細(xì)的分析ARC引用過程,
  • 建議如果我們未發(fā)現(xiàn)表示內(nèi)存泄漏的紅x,但是我們想進(jìn)一步評(píng)估某個(gè)對(duì)象對(duì)于內(nèi)存的應(yīng)用,可以看看Allocations模版的折線圖,反復(fù)執(zhí)行從 創(chuàng)建對(duì)象 -> 銷毀對(duì)象 這個(gè)過程,如果總占用內(nèi)存數(shù)會(huì)隨之增加,這說明這個(gè)對(duì)象沒有釋放,有些時(shí)候雖然占用的對(duì)象不是很嚴(yán)重,但是也會(huì)增加占用內(nèi)存,因此必須釋放這個(gè)對(duì)象
  • 提示:有些情況下,對(duì)象沒有釋放是無法檢測(cè)到的,反復(fù)監(jiān)測(cè)內(nèi)存占用也沒有明顯的增加,這是最好在配置比較低的設(shè)備上測(cè)試一下。

文章學(xué)習(xí)路徑:關(guān)于Instruments-Leaks工具的歸納總結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容