轉自wufawei的博客當你的應用提交到App Store或者各個渠道之后,請問你多久會拿到crash文件?你如何分析crash文件的呢??
上傳crash文件你的應用應當有模塊能夠在應用程序crash的時候上傳crash信息。 要么通過用戶反饋拿到crash文件,要么借助自己或第3方的crash上傳模塊拿到crash文件。 今天要分析的場景是你拿到用戶的.crash文件之后,如何符合化crash文件(Symbolicating crash logs)的3種方法。幫助盡快找到crash原因。?
crash文件例子crash文件的部分內容: Last Exception Backtrace:0 CoreFoundation 0x30acaf46 exceptionPreprocess + 1261 libobjc.A.dylib 0x3af0b6aa objc_exception_throw + 342 CoreFoundation 0x30a0152e -[__NSArrayM objectAtIndex:] + 2263 appName 0x000f462a 0x4000 + 9846184 appName 0x00352aee 0x4000 + 3468014…18 appName 0x00009404 0x4000 + 21508?
大家一眼就能看到: 2 CoreFoundation 0x30a0152e -[__NSArrayM objectAtIndex:] + 226 這一行有問題。?
但是,第3行和第4行的: 3 appName 0x000f462a 0x4000 + 9846184 appName 0x00352aee 0x4000 + 3468014 并沒有指出到底是app的那個模塊導致的問題,如何排查呢? 有如下3種方法
?方法1 使用XCode這種方法可能是最容易的方法了。 需要使用Xcode符號化 crash log,你需要下面所列的3個文件:1. crash報告(.crash文件)2. 符號文件 (.dsymb文件)3. 應用程序文件 (appName.app文件,把IPA文件后綴改為zip,然后解壓,Payload目錄下的appName.app文件), 這里的appName是你的應用程序的名稱。 把這3個文件放到同一個目錄下,打開Xcode的Window菜單下的organizer,然后點擊Devices tab,然后選中左邊的Device Logs。 然后把.crash文件拖到Device Logs或者選擇下面的import導入.crash文件。 這樣你就可以看到crash的詳細log了。 如下圖:?
方法2 使用命令行工具symbolicatecrash有時候Xcode不能夠很好的符號化crash文件。我們這里介紹如何通過symbolicatecrash來手動符號化crash log。 在處理之前,請依然將“.app“, “.dSYM”和 ".crash"文件放到同一個目錄下。現在打開終端(Terminal)然后輸入如下的命令:export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer? 然后輸入命令:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash appName.crash appName.app > appName.log? 現在,符號化的crash log就保存在appName.log中了。
?方法3 使用命令行工具atos如果你有多個“.ipa”文件,多個".dSYMB"文件,你并不太確定到底“dSYMB”文件對應哪個".ipa"文件,那么,這個方法就非常適合你。 特別當你的應用發布到多個渠道的時候,你需要對不同渠道的crash文件,寫一個自動化的分析腳本的時候,這個方法就極其有用。 這里先介紹一個概念:UUID 什么是UUID每一個可執行程序都有一個build UUID來唯一標識。Crash日志包含發生crash的這個應用(app)的 build UUID以及crash發生的時候,應用加載的所有庫文件的[build UUID]。 那如何知道crash文件的UUID呢? 可以用:grep "appName armv" *crash? 或者grep --after-context=2 "Binary Images:" *crash? 可以得到類似如下的結果:appName.crash-0x4000 - 0x9e7fff appName armv7 <8bdeaf1a0b233ac199728c2a0ebb4165> /var/mobile/Applications/A0F8AB29-35D1-4E6E-84E2-954DE7D21CA1/appName.crash.app/appName? (請注意這里的0x4000,是模塊的加載地址,后面用atos的時候會用到) 如何找到app的UUID可以使用命令:xcrun dwarfdump -–uuid比如:
xcrun dwarfdump --uuid appName.app/appName
結果如下:
UUID: 8BDEAF1A-0B23-3AC1-9972-8C2A0EBB4165 (armv7) appName.app/appName
UUID: 5EA16BAC-BB52-3519-B218-342455A52E11 (armv7s) appName.app/appName
這個app有2個UUID,表明它是一個fat binnary。
它能利用最新硬件的特性,又能兼容老版本的設備。
對比上面crash文件和app文件的UUID,發現它們是匹配的:
8BDEAF1A-0B23-3AC1-9972-8C2A0EBB4165
用atos命令來符號化某個特定模塊加載地址
命令是:
atos [-o AppName.app/AppName] [-l loadAddress] [-arch architecture]
親測,下面3種都可以:
xcrun atos -o appName.app.dSYM/Contents/Resources/DWARF/appName -l 0x4000 -arch armv7
xcrun atos -o appName.app.dSYM/Contents/Resources/DWARF/appName -arch armv7
xcrun atos -o appName.app/appName -arch armv7
(注:這3行選任意一行執行都可以達到目的,其中0x4000是模塊的加載地址,從上面的章節可以找到如何得到這個地址。)
文章開頭提到crash文件中有如下兩行,
* 3 appName 0x000f462a 0x4000 + 984618
* 4 appName **0x00352aee** 0x4000 + 3468014
在執行了上面的:
xcrun atos -o appName.app.dSYM/Contents/Resources/DWARF/appName -l 0x4000 -arch armv7
之后,輸入如下地址:
0x00352aee
(crash文件中的第4行:4 appName **0x00352aee** 0x4000 + 3468014)
可以得到結果:
-[UIScrollView(UITouch) touchesEnded:withEvent:] (in appName) (UIScrollView+UITouch.h:26)
這樣就找到了應用種到底是哪個模塊導致的crash問題。
總結
本文分析了拿到用戶的.crash文件之后,如何符合化crash文件的3種方法,分別有其適用場景,方法3適用于自動化crash文件的分析。
參見:
分析iOS Crash文件:符號化iOS Crash文件的3種方法 - CocoaChina 蘋果開發中文站 - 最熱的iPhone開發社區 最熱的蘋果開發社區 最熱的iPad開發社區
Technical Q&A QA1765: How to Match a Crash Report to a Build