轉(zhuǎn)自wufawei的博客當(dāng)你的應(yīng)用提交到App Store或者各個(gè)渠道之后崔泵,請(qǐng)問你多久會(huì)拿到crash文件挂滓?你如何分析crash文件的呢嫉髓??
上傳crash文件你的應(yīng)用應(yīng)當(dāng)有模塊能夠在應(yīng)用程序crash的時(shí)候上傳crash信息倘零。 要么通過用戶反饋拿到crash文件癌蚁,要么借助自己或第3方的crash上傳模塊拿到crash文件幻梯。 今天要分析的場景是你拿到用戶的.crash文件之后,如何符合化crash文件(Symbolicating crash logs)的3種方法努释。幫助盡快找到crash原因碘梢。?
crash文件例子crash文件的部分內(nèi)容: 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的那個(gè)模塊導(dǎo)致的問題煞躬,如何排查呢? 有如下3種方法
?方法1 使用XCode這種方法可能是最容易的方法了逸邦。 需要使用Xcode符號(hào)化 crash log恩沛,你需要下面所列的3個(gè)文件:1. crash報(bào)告(.crash文件)2. 符號(hào)文件 (.dsymb文件)3. 應(yīng)用程序文件 (appName.app文件,把IPA文件后綴改為zip缕减,然后解壓雷客,Payload目錄下的appName.app文件), 這里的appName是你的應(yīng)用程序的名稱。 把這3個(gè)文件放到同一個(gè)目錄下桥狡,打開Xcode的Window菜單下的organizer搅裙,然后點(diǎn)擊Devices tab,然后選中左邊的Device Logs裹芝。 然后把.crash文件拖到Device Logs或者選擇下面的import導(dǎo)入.crash文件部逮。 這樣你就可以看到crash的詳細(xì)log了。 如下圖:?
方法2 使用命令行工具symbolicatecrash有時(shí)候Xcode不能夠很好的符號(hào)化crash文件嫂易。我們這里介紹如何通過symbolicatecrash來手動(dòng)符號(hào)化crash log兄朋。 在處理之前,請(qǐng)依然將“.app“, “.dSYM”和 ".crash"文件放到同一個(gè)目錄下【娲睿現(xiàn)在打開終端(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? 現(xiàn)在蜈漓,符號(hào)化的crash log就保存在appName.log中了。
?方法3 使用命令行工具atos如果你有多個(gè)“.ipa”文件宫盔,多個(gè)".dSYMB"文件融虽,你并不太確定到底“dSYMB”文件對(duì)應(yīng)哪個(gè)".ipa"文件,那么灼芭,這個(gè)方法就非常適合你有额。 特別當(dāng)你的應(yīng)用發(fā)布到多個(gè)渠道的時(shí)候,你需要對(duì)不同渠道的crash文件,寫一個(gè)自動(dòng)化的分析腳本的時(shí)候巍佑,這個(gè)方法就極其有用茴迁。 這里先介紹一個(gè)概念:UUID 什么是UUID每一個(gè)可執(zhí)行程序都有一個(gè)build UUID來唯一標(biāo)識(shí)。Crash日志包含發(fā)生crash的這個(gè)應(yīng)用(app)的 build UUID以及crash發(fā)生的時(shí)候萤衰,應(yīng)用加載的所有庫文件的[build UUID]堕义。 那如何知道crash文件的UUID呢? 可以用:grep "appName armv" *crash? 或者grep --after-context=2 "Binary Images:" *crash? 可以得到類似如下的結(jié)果:appName.crash-0x4000 - 0x9e7fff appName armv7 <8bdeaf1a0b233ac199728c2a0ebb4165> /var/mobile/Applications/A0F8AB29-35D1-4E6E-84E2-954DE7D21CA1/appName.crash.app/appName? (請(qǐng)注意這里的0x4000脆栋,是模塊的加載地址倦卖,后面用atos的時(shí)候會(huì)用到) 如何找到app的UUID可以使用命令:xcrun dwarfdump -–uuid比如:
xcrun dwarfdump --uuid appName.app/appName
結(jié)果如下:
UUID: 8BDEAF1A-0B23-3AC1-9972-8C2A0EBB4165 (armv7) appName.app/appName
UUID: 5EA16BAC-BB52-3519-B218-342455A52E11 (armv7s) appName.app/appName
這個(gè)app有2個(gè)UUID,表明它是一個(gè)fat binnary椿争。
它能利用最新硬件的特性怕膛,又能兼容老版本的設(shè)備。
對(duì)比上面crash文件和app文件的UUID秦踪,發(fā)現(xiàn)它們是匹配的:
8BDEAF1A-0B23-3AC1-9972-8C2A0EBB4165
用atos命令來符號(hào)化某個(gè)特定模塊加載地址
命令是:
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行選任意一行執(zhí)行都可以達(dá)到目的,其中0x4000是模塊的加載地址椅邓,從上面的章節(jié)可以找到如何得到這個(gè)地址柠逞。)
文章開頭提到crash文件中有如下兩行,
* 3 appName 0x000f462a 0x4000 + 984618
* 4 appName **0x00352aee** 0x4000 + 3468014
在執(zhí)行了上面的:
xcrun atos -o appName.app.dSYM/Contents/Resources/DWARF/appName -l 0x4000 -arch armv7
之后希坚,輸入如下地址:
0x00352aee
(crash文件中的第4行:4 appName **0x00352aee** 0x4000 + 3468014)
可以得到結(jié)果:
-[UIScrollView(UITouch) touchesEnded:withEvent:] (in appName) (UIScrollView+UITouch.h:26)
這樣就找到了應(yīng)用種到底是哪個(gè)模塊導(dǎo)致的crash問題边苹。
總結(jié)
本文分析了拿到用戶的.crash文件之后,如何符合化crash文件的3種方法裁僧,分別有其適用場景个束,方法3適用于自動(dòng)化crash文件的分析。
參見:
Technical Q&A QA1765: How to Match a Crash Report to a Build