你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 說說iOS與內存管理(中)

說說iOS與內存管理(中)

編輯:IOS開發基礎

1435029351780348.jpg

  • 相關文章:說說iOS與內存管理(上)

接著上文簡單整理下iOS常見內存問題及排查相關的工具和方法。

上篇日志是6月份寫的,由於工作的內容比較豐富,這麼久一直沒能更新blog,有點小遺憾,這是到這是2015年8月最後一天,趁著8月還沒過,趕快把這篇補上。

0. 內存工具

針對iOS開發,我們所能使用的內存排查工具選擇其實並不算特別多。最主要的調試工具就是Instruments。然而,如果仔細探查細節,Instruments還是集成了很多不錯的調試模板/Library的。

本文針對如下幾類應用場景,對通用的調試方法做基本介紹:

  • 最基本最常用的內存問題場景——內存洩露、過度釋放

  • malloc相關的堆內存分配問題排查相關工具

  • 其它內存工具

1. 內存洩露與過度釋放

我們應該都知道,iOS開發過程中,使用Objective-C分配的堆內存都是通過引用計數來做保留和釋放的。一塊內存初始分配,引用計數為1,此後每新增一個強引用,引用計數增加1;釋放正好相反,每一次release,引用計數減1,直到為0,對象所用內存被真正free掉,以被再次復用。然而,實際開發當中,總有一些原因導致引用計數無法按正常邏輯減少到0,或者減少到0之後仍然被調用release,前者是內存洩露,後者則是過度釋放。

當內存洩露發生時,運行的App不會直接第發生明顯問題,但廢棄內存得不到回收,在長時間持續運行後,App進程會由於可用內存不斷變低而被kill或帶來其它隱患。

避免內存洩露,首要是有良好的代碼習慣,避免循環引用、會用weak,其次可以通過Analyze來進行靜態代碼檢查,以發現在語法上顯而易見的內存洩露問題。但更多時候,內存洩露是運行時的問題,這時可用Instruments中的Allocation和Leaks來不斷重復操作App,發現和定位內存洩露點。

當運行時發生顯示內存洩露時,Leaks會在時間軸上標出紅色指示線,同時在Instruments的下方會列出調用細節,結合系統提供的malloc歷史,其中包含引用計數變化情況,以及調用棧可以很直接地找到洩露原因。

同時對於一些“隱式”的情況,需要反復操作,同時觀察Allocation中只增不減,一直創建新對象而不釋放老對象的情況。

過度釋放,是對同一個對象釋放了過多的次數,其實當引用計數降到0時,對象占用的內存已經被釋放掉,此時指向原對象的指針就成了“懸垂指針”,如若再對其進行任何方法的調用,(原則上)都會直接crash(然而由於某些特殊的情況,不會馬上crash)。

對於這種問題,可以直接使用Zombie,當過度釋放發生時會立即停在發生問題的位置,同時結合內存分配釋放歷史和調用棧,可以發現問題。

至於上文提到的不會crash的原因,其實有很多,比如:

  • 對象內存釋放時,所用內存並沒有完全被擦除,仍有舊對象部分數據可用

  • 原內存位置被寫入同類或同樣結構的數據

2. malloc庫提供的相關工具

上一段提到,對象釋放時,所用內存並沒有完全被擦除,仍有舊對象部分數據可用,如果不使用Zombie調試,App可能不會直接crash。對付這種情況,其實很簡單,可以在對象內存釋放時寫入無意義數據,如0×55,0xaa等,而系統已經幫我們做了這個工具,那就是Scribble,在Xcode的Edit Scheme裡,Diagnostics Tab下勾選Enable Scribble。

Scribble其實是malloc庫(libsystem_malloc.dylib)自身提供的調試方案,除了Scribble,malloc還提供了很多其它的調試工具/方案,在Diagnostics Tab下你應該都看到了。其實,malloc可用的工具還不止這些,通過環境變量至少還可以添加如下調試參數:

  • MallocLogFile

  • MallocGuardEdges

  • MallocDoNotProtectPrelude

  • MallocDoNotProtectPostlude

  • StackLogging

  • StackLoggingNoCompact

  • MallocCorruptionAbort

  • MallocNanoZone

  • MallocCheckHeap

其中,有幾個參數是和記錄分配歷史的日志有關的。

除此之外,Xcode裡還提供了Guard malloc,這個是等同於默認malloc庫功能的另外一個調試庫,為了定位大內存越界訪問問題,不過只能在模擬器上使用(個人分析是因為真機根本承受不起保護頁內存消耗)。

對以上參數的實現細節感興趣的,可以參看蘋果開放出來的malloc源碼。

3. 其它

下面我還想對Instruments裡的三樣東西做簡要介紹:

  • Allocation

  • Activity Monitor

  • VM Tracker

Allocation針對堆內存及匿名映射的情況提供了詳細的數據,包括某類對象有多少個,對象的具體地址,占用多大內存等。通過Allocation,可以對我們開發中實際接觸到的內存有非常全面的把握。

Activity Monitor則從系統的層面,對主要進程的CPU、內存、網絡等數據做分析。從內存方面看,我們可以知道占用系統內存最大的5個App,它提供的數據包含了實際物理內存和虛擬內存部分。

VM Tracker則可以告訴我們哪些部分是Dirty的,Dirty的數據系統不會直接清理掉,因為這些數據是被寫過的,無法通過外部存儲直接生成,只能維持在內存當中。此外,通過VM Tracker我們還可以看到Region Map,看到進程地址空間各部分的映射情況。

除了上面提到的這些,對於詭異的內存問題,我們可以對Xcode7中的Address Sanitizer期待和試用下,也許它真得能幫我們解決好多問題!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved