經驗之道:最有效的iOS內存泄漏檢測

版權聲明:本文由胡濤原創文章,轉載請註明出處: 
文章原文連接:https://www.qcloud.com/community/article/125模塊化

來源:騰雲閣 https://www.qcloud.com/community工具

 

使用instruments工具來更好的調試咱們的工程中新開發或者修改過的模塊的內存情況。性能

iOS設備性能愈來愈好,iOS App 也相應的變得愈來愈龐大,App代碼的量級也在快速的增加,開發一個小的模塊在工程中調試變的愈來愈難,一般咱們是經過觀察Allocation的內存變化高低,或者內存分配快照對比來尋找泄漏的狀況,但這幾乎是一個讓人抓狂的調試方法,尤爲在很是複雜的項目中,一個模塊的推入與推出在Allocation上的變化微乎其微,並且受制於項目的複雜度,各類你所未知的對象的建立與銷燬帶來的Allocation圖形高度的影響,對於觀察Allocation的分配圖像的高低變化來講,可以參考的意義就變的很是有限。測試

經過過去參與過的複雜大型的iOS項目開發經驗,開發新的模塊的時候,總結出了一套完整的iOS內存自測的方法,經過Instruments來逐步跟蹤檢測咱們建立和主動銷燬的對象是否真的銷燬了。調試

在演示以前,須要強調一件事情就是,以文件夾目錄做爲你的空間命名很重要,請遵循開發新模塊的時候使用你的模塊的命名做爲前綴。由於iOS沒有命名空間這個東西,一般爲了保證不衝突,咱們都是以項目前綴+空間命名來保證文件的獨立性,空間名就是目錄和模塊的名字了。這個在咱們使用instruments進行內存檢測的時候是很是重要的,接下來的使用過程就能夠證明這一良好的命名習慣所帶來的巨大好處,不僅是優雅,更重要的是幫助。orm

除了命名,還有一件很重要的事情就是,你須要對你的模塊在各類UI操做或者事件發生過程的狀況下,對你的對象分配過程要很是很是清楚,由於這樣,你才能看出相應的變化,哪些對象是應該存在的,哪些對象在某個動做結束後是一定會銷燬的,這個應該很容易,你應該純自然的就知道,由於你開發的整個邏輯。對象

最近在開發一個新的模塊,正好須要在內存方面作一個完整的自測,既要確保效率,也要確保內存的正確分配與釋放。blog

重要:(如下教程開始全部示例圖片,請自行點擊圖片看大圖,看的倍兒清楚!)教程

  1. 首先,我先上圖,看一下個人命名組織結構,遵循的就是模塊化的命名,由於手Q的跨部門合做,因此用部門標記做爲前綴。代碼首先是要讓人來看的,是人在維護程序,因此可讀性很是重要,在開發完這些功能後,我對於全部對象在運行過程當中的建立與銷燬是很清楚的。
    事件

  2. 接下來我要進入instruments來進行內存測試,profile運行Leaks就OK了,就會進入下面看到的界面,詳細講解一下都是什麼吧,這些對對象怎麼分配內存的很重要。

  3. 而後我就須要操做模擬器來進入我所開發的功能模塊,會看到很是複雜的對象分配狀況,因此這一步很是關鍵,我只須要在搜索框搜索模塊的前綴就能夠只顯示當前模塊所涉及的對象分配與銷燬狀況,以下圖,進入了的模塊視圖:

  4. 接下來我執行一個環境查詢的命令,再看一下執行以後的內存分配狀況。

  5. 個人邏輯是這樣的,點擊一次建立一個命令(VASDebugPlatformServerCmd),經過這個命令初始化並執行一個任務,任務結束後就銷燬這個任務對象(VASDebugPlatformBaseOperation),相應的命令也做爲任務的成員一塊兒被銷燬。因此,在動做執行完後咱們應該能夠在已銷燬對象中找到這個實例,運行截圖以下:

  6. 我看到任務是已經被銷燬了的,但是用來初始化的命令對象爲何沒有被銷燬,我須要深挖一下這個命令對象(VASDebugPlatformServerCmd)的引用計數到底怎麼發生變化的,就須要用到下面的步驟了,按照圖解去深挖它:

  7. 我挖到命令對象的內部,一路挖到底,我發現命令對象最終的引用計數是1,證實它還在內存中活着,截圖是這樣的:

  8. 因此,我就看看,任務對象銷燬了,那任務對象到底發生了什麼事 截圖是這樣的:

  9. 我就是不死心,我就是要看到,究竟是不是真的呢,爲了進一步佐證命令對象在內存中,我在對象內部觀察了一個內存檢測的通知,收到通知後彈一個alert出來,若是對象被銷燬了,它確定收不到這個通知,以下面截圖所示的工做:

  10. 由於這是我本身寫的邏輯,我很清楚對象在哪裏分配內存,而後我就去查代碼,命令對象到底經歷了什麼,從開始到結束的執行過程是什麼樣的:


  11. 看完上面的截圖,再去看命令對象的引用計數變化就知道爲何了:
  12. 固然,我也看出了爲何引用計數沒有歸零,因此,我在下面進行了修復:
  13. 再次profile->Leaks , 而後我再作一次查詢任務,看看此次命令對象的引用計數變化,命令對象被釋放了!:

總結:

  • 保持你的模塊擁有一個良好的命名空間

  • 請深入而且清楚的知道,觸發什麼事件,執行UI動做以後,你的對象分配會是什麼樣的,誰此刻應該存在內存中,誰應該被銷燬,而後利用上面的原理去查看,它是否是被銷燬了,若是沒有被銷燬,那麼你應該去查你的代碼,到底在執行過程當中,哪裏沒有平衡引用計數。

  • 此方法在ARC和MRC的狀況都是適用的,目標是觀察具體哪一個實例對象沒有被銷燬,而後根據引用計數變化跳轉到代碼中去確認哪裏出現了內存問題。

文章來源於公衆號:小時光茶社(Tech Teahouse)

相關文章
相關標籤/搜索