查找 iOS 應用的內存問題

本文列舉的不是查找 iOS 應用內存問題的必要流程,只是講述筆者在干這檔子事兒的時候充岛,可能會用到的手段而已。??

Clang Static Analyzer

在應用運行起來之前,我們就能通過 Xcode 集成的靜態(tài)分析工具 Clang Static Analyzer锋拖,分析下面幾種類型的代碼問題:

  • Logic flaws: 讀取未初始化的變量、解引用空指針等等祸轮;
  • Memory management flaws:內存泄露等兽埃;
  • Dead store:沒被使用的變量;
  • API usage flaws:返回值等不符合 API 的要求适袜;

靜態(tài)分析的結果通常是基于某種假設邏輯而推斷產生的柄错,所以是否要修改代碼這一決定不能完全交給 analyzer。諸如“如何忽略特定的 dead store”、“如何告訴 analyzer 循壞塊一定會進入”等常見問題售貌,在這個 FAQ 中都列了出來给猾。

更方便的是,使用 scan-build 能在命令行中分析颂跨,還能導出 html 方便查看分析結果:

scan-build -o DIR_TO_STORE_RESULTS xcodebuild -configuration Debug -workspace PATH_TO_YOUR_WORKSPACE -scheme YOUR_SCHEME_NAME

如果你的是 project 而不是 workspace 就寫 -project PATH_TO_YOUR_PROJECT……好吧這就是 xcodebuild 的參數(shù)而已跟 scan-build 無關敢伸。

bug_summary.png

上圖僅僅是 Bug Summary,下面才是 Report恒削,比較私密就不截了池颈,內容和用 Xcode 分析一樣,給出具體邏輯的判定流程钓丰,指出錯誤躯砰。筆者覺得這一步可以添加到持續(xù)集成中,這樣每天早上都能看到前一天可能新增的代碼問題携丁。

Leaks

Leaked Memory 指的是丟失引用的內存琢歇。打開 Leaks,盡管操作你的業(yè)務邏輯就好梦鉴,Leaks Check 那一欄出現(xiàn)紅色交叉就是檢測到泄露的地方矿微,選中 Leaks Object,點擊右邊的 E 按鈕(Extended Detail)可以看到調用棧尚揣,幫助定位問題涌矢。

leaks.png

不過要注意的是,任何一個大型軟件都不可能是完美的快骗,所以 Cocoa Touch 本身也是可能發(fā)生泄漏的娜庇,所以對于那些調用棧沒有用戶代碼而且你絞盡腦汁都想不明白的泄漏,說不定可以無視它方篮。

但對于 Abandoned Memory 來說名秀,Leaks 就無能為力了。Abandoned Memory 是那些引用沒有丟失藕溅,但不再被使用的內存匕得,在 ARC 下常見于由循環(huán)引用導致的內存不能釋放。譬如說 Push 進入某個 ViewController 之后巾表,再 Pop 回去汁掠,假設這個 ViewController 與其實例變量有循環(huán)引用,那么它們將不會被釋放集币,Leaks 沒辦法檢測到這種內存泄露考阱,于是乎需要 Allocations 這個工具(通常會新建個模板把這兩個工具放在一起用,嗯還有 VM Tracker)鞠苟。

Allocations

在 Push 之前乞榨,使用 Allocations 對當前內存中的 Heap 和 VM Region 進行 Mark Generation秽之,記錄內存的使用狀態(tài),接著 Push 進一個 ViewController 后 Pop 回去吃既,再 Mark 一遍考榨,這樣重復業(yè)務邏輯好幾次,就能發(fā)現(xiàn)每次內存的增長情況鹦倚。前一兩次的快照可能有一些 lib 的緩存董虱,所以要特別留意之后的內存增長情況。

每次 Mark Generation 之后申鱼,Growth 還是會不斷變化的愤诱,這里筆者不清楚是系統(tǒng)延遲釋放內存,還是工具還來不及作對比捐友。我嘗試了下淫半,多點 Mark Generation 幾次或者手動觸發(fā) Memory Warning 可以讓前面的 Growth 快一點穩(wěn)定下來。

track_display.png

將 Track Display 改為 Allocation Density 可以留意到內存分配的動態(tài)匣砖,突然出現(xiàn)的尖峰就是在那段時間拼命地在分配內存科吭,稍微注意下是什么操作引起,說不定能優(yōu)化是吧猴鲫?畢竟堆上的內存分配可不是個輕松活对人。

我們還能再下面看到 Allocation Type 這個選項,Heap 和 VM Regions上的內存都是我們要關注的點拂共。我們實例化的對象牺弄、malloc 分配的內存都在 Heap 上,而 VM Regions 上是我們不能直接接觸的內存宜狐,但這不代表我們不用理會 VM Regions 任由其增長势告。比如 UIImage 對象在 Heap 上可能只有幾十字節(jié),但它代表的圖片在解壓縮后在 Image Region 上可能會占用幾十kb抚恒,甚至更大咱台。再比如,UIView 對象本身也不大俭驮,但是 CALayer backing stores 就不一定不起眼了回溺。

還有,回到 Record Settings混萝,我們常常需要在 Recorded Types 上設置忽略或追蹤特定類型的對象以便于我們分析(這里凸顯了給自己項目的類添加前綴的好處)遗遵,特別是當你已經將目標鎖定在某些類上時,這么做可以讓我們事半功倍譬圣。

Debug Memory Graph

這是 Xcode 8 的新功能瓮恭,就是點了 Debug Memory Graph 之后能看到當前在內存中的各種對象間引用關系雄坪。如果出現(xiàn)紫色框框的感嘆號厘熟,那么可能是有內存問題屯蹦,具體看上面的提示。有一點要提及的是绳姨,如果想看與某個對象的 backtrace登澜,要去 Edit-Scheme-Diagnostics 中把 Malloc Stack 的復選框給勾上,否則你可能找不這玩意兒是在哪里創(chuàng)建的……

第三方的檢測工具

除了官方的提供的工具之外飘庄,筆者還會使用一些的第三個工具脑蠕,最早使用過 HeapInspector-for-iOS 代替 Allocations,直接就在應用內分析 Heap 的增長情況跪削。還有 FBRetainCycleDetector谴仙,通過 DFS 尋找以對象為節(jié)點、強引用關系為邊的有向圖中的環(huán)路碾盐,從而達到找到循環(huán)引用的目的晃跺。上面的兩個庫都有些缺點,比如前者也是要不斷重復業(yè)務邏輯并推斷毫玖,后者要修改代碼才能查找環(huán)路掀虎。而 WeRead 團隊出品的 MLLeaksFinder 解決了這兩個問題,具體可以看他們博客的介紹《MLeaksFinder:精準 iOS 內存泄露檢測工具》以及《MLeaksFinder 新特性》付枫,這個工具在實踐中還是比較好用的烹玉。

最后

還是那句話,上面的所羅列不是查找 iOS 應用內存問題的必要流程阐滩,僅僅是常用的手段二打。另外,還有一點是調試的心態(tài)掂榔,當筆者要去查一個應用的內存問題時址儒,筆者會像個XX一樣,總是想找到內存問題衅疙,不找到不甘心??莲趣,然后會懷疑自己對項目代碼不夠了解、自己調試經驗不足以及工具使用的姿勢不正確等等饱溢。這顯然是一種心理疾病喧伞,望各位以此為鑒,將更多的精力投入到新需求的開發(fā)中绩郎,而不是深陷調試旋渦無法自拔潘鲫。

話說剛來公司一個月就給項目寫了兩個 bug,也是個挺悲傷的故事??肋杖。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末溉仑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子状植,更是在濱河造成了極大的恐慌浊竟,老刑警劉巖怨喘,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異振定,居然都是意外死亡必怜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門后频,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梳庆,“玉大人,你說我怎么就攤上這事卑惜「嘀矗” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵露久,是天一觀的道長胧后。 經常有香客問我,道長抱环,這世上最難降的妖魔是什么壳快? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮镇草,結果婚禮上眶痰,老公的妹妹穿的比我還像新娘。我一直安慰自己梯啤,他們只是感情好竖伯,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著因宇,像睡著了一般七婴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上察滑,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天打厘,我揣著相機與錄音,去河邊找鬼贺辰。 笑死户盯,一個胖子當著我的面吹牛,可吹牛的內容都是我干的饲化。 我是一名探鬼主播莽鸭,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吃靠!你這毒婦竟也來了硫眨?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤巢块,失蹤者是張志新(化名)和其女友劉穎礁阁,沒想到半個月后巧号,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡氮兵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年裂逐,在試婚紗的時候發(fā)現(xiàn)自己被綠了歹鱼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泣栈。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖弥姻,靈堂內的尸體忽然破棺而出南片,到底是詐尸還是另有隱情,我是刑警寧澤庭敦,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布疼进,位于F島的核電站,受9級特大地震影響秧廉,放射性物質發(fā)生泄漏伞广。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一疼电、第九天 我趴在偏房一處隱蔽的房頂上張望嚼锄。 院中可真熱鬧,春花似錦蔽豺、人聲如沸区丑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沧侥。三九已至,卻和暖如春魄鸦,著一層夾襖步出監(jiān)牢的瞬間宴杀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工拾因, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留婴氮,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓盾致,卻偏偏與公主長得像主经,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子庭惜,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容