寫(xiě)在前面:本文會(huì)在最開(kāi)頭將蘋(píng)果官方的文檔Understanding and Analyzing Application Crash Reports進(jìn)行翻譯,但這不僅僅是一篇翻譯的文章,本文會(huì)讓大家更加全面的了解ios的崩潰報(bào)告的獲取、分析、用途。翻譯的時(shí)候我會(huì)結(jié)合自己以往的使用經(jīng)驗(yàn)來(lái)進(jìn)行翻譯。
理解和分析應(yīng)用程序崩潰報(bào)告
重要提示:
當(dāng)應(yīng)用程序崩潰時(shí),創(chuàng)建了一個(gè)崩潰報(bào)告,這是非常有用的了解什么造成的崩潰。本文件包含重要的信息,如何symbolicate,理解和解釋的崩潰報(bào)告。
簡(jiǎn)介
當(dāng)應(yīng)用程序崩潰時(shí),將創(chuàng)建一個(gè)崩潰報(bào)告并存儲(chǔ)在設(shè)備上。崩潰報(bào)告描述的情況下,應(yīng)用程序終止,在大多數(shù)情況下,包括每個(gè)執(zhí)行線程的一個(gè)完整的回溯,通常對(duì)于調(diào)試應(yīng)用中的問(wèn)題是非常有用。你應(yīng)該看看這些崩潰報(bào)告,了解你的應(yīng)用程序有什么崩潰,然后嘗試修復(fù)它們。
有回溯的崩潰報(bào)告需要被符號(hào)化了才可以分析。符號(hào)化(symbolication)成人們可讀的函數(shù)名稱和行號(hào)來(lái)取代內(nèi)存地址。如果你通過(guò)Xcode的設(shè)備窗口來(lái)獲取設(shè)備的崩潰日志,它們將在幾秒鐘后自動(dòng)被符號(hào)化。否則,你將需要自己將崩潰日志符號(hào)化,通過(guò)自己導(dǎo)入崩潰文件到Xcode設(shè)備窗口??吹椒?hào)化(symbolicating)后的崩潰報(bào)告。
低內(nèi)存報(bào)告不同于其他的崩潰報(bào)告,沒(méi)有回朔在這種類型的報(bào)告。當(dāng)?shù)蛢?nèi)存崩潰發(fā)生時(shí),你必須調(diào)查你的內(nèi)存使用模式和對(duì)低內(nèi)存警告的響應(yīng)。此文檔指向了您可能會(huì)發(fā)現(xiàn)有用的多個(gè)內(nèi)存管理引用。
獲取崩潰和低內(nèi)存報(bào)告
調(diào)試部署iOS應(yīng)用程序 討論如何直接從iOS設(shè)備獲取崩潰和內(nèi)存不足的報(bào)道。
在應(yīng)用程序分發(fā)指南中的分析崩潰報(bào)告 討論如何從TestFlight beta測(cè)試者和那些已經(jīng)從App Store下載應(yīng)用程序的用戶中收集崩潰報(bào)告。
symbolicating崩潰報(bào)告
symbolication是解決回溯地址的源代碼的方法或函數(shù)名的過(guò)程,稱為符號(hào)化。沒(méi)有經(jīng)過(guò)符號(hào)化的崩潰報(bào)告,是不能了解具體的崩潰信息的。
注:低內(nèi)存報(bào)告不需要symbolicated。
注:來(lái)自MacOS崩潰報(bào)告通常是已經(jīng)符號(hào)化的,或部分符號(hào)化后的(symbolicated)。
本節(jié)重點(diǎn)symbolicating從iOS,WatchOS,和TVOS的崩潰報(bào)告,但整體過(guò)程類似MacOS。
圖1概述了崩潰報(bào)告和symbolication過(guò)程。

1.當(dāng)編譯器將源代碼翻譯成機(jī)器代碼時(shí),它也會(huì)生成調(diào)試符號(hào),它將編譯后的二進(jìn)制中的每一個(gè)機(jī)器指令映射到源代碼的行源代碼中。根據(jù)調(diào)試信息格式(debug_information_format)編譯設(shè)置,這些調(diào)試符號(hào)存儲(chǔ)在二進(jìn)制或在同伴的調(diào)試符號(hào)文件(dsym)。默認(rèn)情況下,調(diào)試版本的應(yīng)用程序的調(diào)試符號(hào)存儲(chǔ)在編譯后的二進(jìn)制中,而發(fā)布版本的應(yīng)用程序的調(diào)試符號(hào)存儲(chǔ)在相應(yīng)的dsym文中件以減少二進(jìn)制大小。
調(diào)試符號(hào)文件和應(yīng)用程序二進(jìn)制文件與每一個(gè)build生成的UUID捆綁在一起。一個(gè)新的UUID生成是由build一個(gè)應(yīng)用產(chǎn)生的,它應(yīng)用程序每次build(編譯打包)的唯一標(biāo)識(shí)。即使一個(gè)功能相同的可執(zhí)行文件是從相同的源代碼重構(gòu),具有相同的編譯器設(shè)置,也會(huì)有不同的生成的UUID。調(diào)試符號(hào)文件的后續(xù)版本,甚至來(lái)自同一個(gè)源文件,不會(huì)與其他版本的二進(jìn)制文件相混淆。
2.當(dāng)你的歸檔(archive)要分發(fā)的應(yīng)用程序,Xcode會(huì)收集應(yīng)用程序二進(jìn)制隨著.dsym文件,并且存放在home文件夾里。你可以在Xcode的組織者在“歸檔”部分,找到所有你歸檔后(archived)的應(yīng)用。有關(guān)創(chuàng)建存檔的更多信息,可以參考應(yīng)用程序分發(fā)指南。
重要:為了符號(hào)化(symbolicate)從測(cè)試人員,審查程序,和客戶得到的崩潰報(bào)告,你必須保留每個(gè)存檔您的應(yīng)用程序。
3.如果你是通過(guò)App Store發(fā)布的應(yīng)用程序,或使test flight進(jìn)行測(cè)試,你將選擇包括dsym文件到iTunes Connect。在提交對(duì)話框中,選擇“您的應(yīng)用程序的應(yīng)用程序符號(hào)……”。為了接收來(lái)test flight收集的 以及 那些選擇了分享的診斷數(shù)據(jù)的客戶的崩潰報(bào)告,上傳你的dsym文件是必要的 。有關(guān)崩潰報(bào)告服務(wù)的更多信息,可以參考應(yīng)用程序分發(fā)指南。
重要:從app review收到的崩潰報(bào)告將是unsymbolicated,即使你有上傳dsym文件到iTunes Connect。
你需要使用Xcode 來(lái)symbolicate任何從app review得到的崩潰報(bào)告。
看下午中"到symbolicating崩潰報(bào)告Xcode"。
4.當(dāng)你的應(yīng)用程序崩潰時(shí),一個(gè)unsymbolicated崩潰報(bào)告會(huì)被創(chuàng)建并存儲(chǔ)在設(shè)備上。
5.用戶可以按照調(diào)試部署iOS應(yīng)用程序的步驟,直接從他們的設(shè)備中檢索崩潰報(bào)告。如果你的應(yīng)用程序通過(guò)AdHoc or Enterprise distribution發(fā)布的,這是從你的用戶獲取崩潰報(bào)告的唯一途徑。
6.從設(shè)備檢索得到的未符號(hào)化的(unsymbolicated)崩潰報(bào)告需要使用Xcode來(lái)符號(hào)化(symbolicated)。Xcode使用您的應(yīng)用程序的二進(jìn)制在源代碼中的源位置的回溯替換每個(gè)地址相關(guān)聯(lián)的dsym文件。其結(jié)果是一個(gè)符號(hào)化的(symbolicated)崩潰報(bào)告。
7.如果用戶選擇了與蘋(píng)果共享診斷數(shù)據(jù),或者如果用戶通過(guò)TestFlight安裝了你的應(yīng)用程序,崩潰報(bào)告會(huì)被上傳到應(yīng)用商店。
8.App Store 符號(hào)化崩潰報(bào)告 并且將類似的崩潰報(bào)告分組。類似的崩潰報(bào)告的集合被稱為崩潰點(diǎn)。
9.符號(hào)化的崩潰報(bào)告是在Xcode's Crashes organizer提供給你的。
Bitcode
Bitcode是一個(gè)編譯程序的中間表示。當(dāng)你可以用bitcode來(lái) archive an application,編譯器產(chǎn)生的二進(jìn)制文件包含bitcode而不是機(jī)器代碼。一旦二進(jìn)制已經(jīng)上傳到App Store,這可以被編譯成機(jī)器碼。App Store在將來(lái),在沒(méi)有任何行動(dòng)的一部分的情況下,利用未來(lái)的改進(jìn)的編譯器,再次編譯。

因?yàn)槟愕亩M(jìn)制最后的編譯出現(xiàn)在App Store,Mac將不包含符號(hào)化從應(yīng)用程序?qū)彶榛蛴脩舭l(fā)給你他們從設(shè)備中取得的崩潰報(bào)告所需要的調(diào)試符號(hào)文件(.dsym)。雖然dsym文件是您歸檔應(yīng)用程序(archive your application)的時(shí)候產(chǎn)生的,它是為bitcode二進(jìn)制并不能用來(lái)symbolicate崩潰報(bào)告。App Store在你從Xcode或從iTunes Connect網(wǎng)站,可以獲得編譯的bitcode并且可以下載的過(guò)程中,產(chǎn)生dsym文件。符號(hào)化從應(yīng)用程序?qū)彶榛蛴脩舭l(fā)給你他們從設(shè)備中取得的崩潰報(bào)告,你必須下載這些dsym文件。崩潰報(bào)告獲得通過(guò)崩潰報(bào)告服務(wù)將自動(dòng)symbolicated。
重要:二進(jìn)制應(yīng)用程序商店會(huì)比最初二進(jìn)制編譯,有不同的UUID
從Xcode獲取dSYMs文件
1.下載dsyms文件
在歸檔管理中選擇相應(yīng)的歸檔并下載dsyms文件


2.在歸檔出的文件中找到dSYMs文件



確定崩潰報(bào)告是否被符號(hào)化

符號(hào)化崩潰報(bào)告
1.符號(hào)化用xcode編譯安裝軟件的設(shè)備上的崩潰報(bào)告
當(dāng)應(yīng)用在設(shè)備上運(yùn)行,遇到崩潰的時(shí)候會(huì)產(chǎn)生崩潰日志。如果這個(gè)應(yīng)用是用xcode直接在設(shè)備上編譯運(yùn)行的,那么就可以將手機(jī)連接到編譯的時(shí)候所用的電腦上,打開(kāi)xcode,在Window的Devices中去查看日志。找到日志的時(shí)候,xcode會(huì)自己去符號(hào)化崩潰日志。



2.符號(hào)化用安裝包安裝在測(cè)試設(shè)備上的應(yīng)用所產(chǎn)生的崩潰日志
符號(hào)化的時(shí)候需要準(zhǔn)備symbolicatecrash文件 .dSYM文件 以及.app文件
符號(hào)化前先檢查一下三者的uuid是不是一致的,只有是一致的才能符號(hào)化成功。
查看xx.app文件的uuid的方法:
dwarfdump --uuid xxx.app/xxx (xxx工程名)
查看xx.app.dSYM文件的uuid的方法令:
dwarfdump --uuid xxx.app.dSYM (xxx工程名)
而.crash的uuid位于,crash日志中的Binary Images:中的第一行尖括號(hào)內(nèi)。如:armv7 <8bdeaf1a0b233ac199728c2a0ebb4165>
將三種文件拷貝到同一個(gè)目錄中,在終端中使用命令
./symbolicatecrash ./.crash ./.app.dSYM > xxx.crash來(lái)解析崩潰日志。

如果想今后解析日志的時(shí)候更方便一點(diǎn),特別是解析多個(gè)崩潰日志的時(shí)候,如果一個(gè)一個(gè)去解析的話,很花費(fèi)時(shí)間的。我的話,會(huì)將這些寫(xiě)到一個(gè)腳本中,解析的時(shí)候就只用執(zhí)行腳本,就可以很方便快捷的獲取到崩潰日志。
3.獲取并符號(hào)化線上的崩潰報(bào)告
一.通過(guò)打包上線時(shí)的xcode來(lái)獲取線上的崩潰報(bào)告
線上app的崩潰日志會(huì)被app store收集并符號(hào)化分組。類似的崩潰報(bào)告的集合被稱為崩潰點(diǎn)。(如果用戶選擇了與蘋(píng)果共享診斷數(shù)據(jù),這些崩潰日志才會(huì)被收集并被符號(hào)化)

在點(diǎn)擊相應(yīng)應(yīng)用后,會(huì)顯示此應(yīng)用的崩潰集合??梢钥吹矫恳粋€(gè)集合中都會(huì)有很多個(gè)設(shè)備,如果右鍵進(jìn)去查看的話,會(huì)看到很多文件。


再次右鍵進(jìn)去查看的話,會(huì)最終看到詳細(xì)的崩潰日志

當(dāng)選中了一個(gè)崩潰集合后,如果選擇在項(xiàng)目中打開(kāi),會(huì)在項(xiàng)目代碼中找到具體出問(wèn)題的代碼



二、通過(guò)友盟等第三方工具來(lái)獲取崩潰日志
崩潰日志列表

其中的一個(gè)崩潰日志

崩潰的代碼的位置,這個(gè)是最關(guān)鍵的,可以通過(guò)這個(gè)來(lái)找到代碼中的出問(wèn)題的地方

export dSYMPath="$(find ~/Library/Developer/Xcode -iname '*.dSYM' -print0 | xargs -0 dwarfdump -u | grep C0349572-9622-3A00-81D0-4DDE0E00DC7A | sed -E 's/[/]+//' | head -n 1)";是為了找到歸檔時(shí)候產(chǎn)生的dsym文件的路徑
dwarfdump --arch=armv7 --lookup 0x426031 "$dSYMPath"是符號(hào)化的關(guān)鍵,可以找出出問(wèn)題的地方。

分析符號(hào)化后的崩潰報(bào)告
1.頭部
每個(gè)崩潰報(bào)告都會(huì)以一個(gè)頭部開(kāi)始
Listing 4 Excerpt of the header from a crash report.
Incident Identifier: B6FD1E8E-B39F-430B-ADDE-FC3A45ED368C
CrashReporter Key: f04e68ec62d3c66057628c9ba9839e30d55937dc
Hardware Model: iPad6,8
Process: TheElements [303]
Path: /private/var/containers/Bundle/Application/888C1FA2-3666-4AE2-9E8E-62E2F787DEC1/TheElements.app/TheElements
Identifier: com.example.apple-samplecode.TheElements
Version: 1.12
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: com.example.apple-samplecode.TheElements [402]
Date/Time: 2016-08-22 10:43:07.5806 -0700
Launch Time: 2016-08-22 10:43:01.0293 -0700
OS Version: iPhone OS 10.0 (14A5345a)
Report Version: 104
以下的值是特別值得注意的:
Incident Identifier: 一個(gè)唯一的標(biāo)識(shí). 不會(huì)存在共用一個(gè)標(biāo)識(shí)的崩潰報(bào)告.
CrashReporter Key:是與設(shè)備標(biāo)識(shí)相對(duì)應(yīng)的唯一鍵值。雖然它不是真正的設(shè)備標(biāo)識(shí)符,但也是一個(gè)非常有用的情報(bào):如果你看到100個(gè)崩潰日志的CrashReporter Key值都是相同的,或者只有少數(shù)幾個(gè)不同的CrashReport值,說(shuō)明這不是一個(gè)普遍的問(wèn)題,只發(fā)生在一個(gè)或少數(shù)幾個(gè)設(shè)備上。
Process: 是應(yīng)用名稱。中括號(hào)里面的數(shù)字是閃退時(shí)應(yīng)用的進(jìn)程ID。
Version: 崩潰進(jìn)程的版本號(hào). 這個(gè)值包含在 CFBundleVersion and CFBundleVersionString中.
Code Type: 崩潰日志所在設(shè)備的架構(gòu). 會(huì)是ARM-64, ARM, x86-64, or x86中的一個(gè).
OS Version: 崩潰發(fā)生時(shí)的系統(tǒng)版本
異常信息
異常信息會(huì)列出異常的類型、位置。
以下的內(nèi)容是摘錄的一個(gè)崩潰報(bào)告的異常代碼段,該崩潰報(bào)告是一個(gè)進(jìn)程由于一個(gè)未捕獲的異常而崩潰產(chǎn)生的。
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Triggered by Thread: 0
以下的內(nèi)容是摘錄于一個(gè)因?yàn)榭罩羔樀脑L問(wèn)而崩潰產(chǎn)生的崩潰報(bào)告的異常代碼段
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000000
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [0]
Triggered by Thread: 0
異常信息中可能出現(xiàn)的字段的解釋如下:
Exception Codes: 處理器的具體信息有關(guān)的異常編碼成一個(gè)或多個(gè)64位進(jìn)制數(shù)。通常情況下,這個(gè)區(qū)域不會(huì)被呈現(xiàn),因?yàn)閷惓4a解析成人們可以看懂的描述是在其它區(qū)域進(jìn)行的。
Exception Subtype: 供人們可讀的異常代碼的名字
Exception Message: 從異常代碼中提取的額外的可供人們閱讀的信息.
Exception Note: 不是特定于一個(gè)異常類型的額外信息.如果這個(gè)區(qū)域包含SIMULATED (這不是一個(gè)崩潰)然后進(jìn)程沒(méi)有崩潰,但是被watchdog殺掉了
Termination Reason: 當(dāng)一個(gè)進(jìn)程被終止的時(shí)的原因。
Triggered by Thread: 異常所在的線程.
下面的小節(jié)將介紹一些最常見(jiàn)的異常類型。
Bad Memory Access [EXC_BAD_ACCESS // SIGSEGV // SIGBUS]
進(jìn)程試圖訪問(wèn)無(wú)效的內(nèi)存,或試圖以內(nèi)存的保護(hù)級(jí)別所不允許的方式去訪問(wèn)內(nèi)存(例如,寫(xiě)入到只讀存儲(chǔ)器)。異常類型字段(Exception Subtype)包含一個(gè)kern_return_t描述錯(cuò)誤,和錯(cuò)誤的訪問(wèn)的內(nèi)存地址。
這里是調(diào)試一個(gè)Bad Memory Access的一些小技巧:
1.如果objc_msgSend或者objc_release在回溯(Backtraces)的頂部附近,這個(gè)進(jìn)程可能是嘗試給一個(gè)釋放的對(duì)象發(fā)送消息。你應(yīng)該用Zombies instrument(調(diào)試僵尸對(duì)象的工具)來(lái)更好的理解這個(gè)崩潰。
2.如果gpus_ReturnNotPermittedKillClient在回溯的頂部附近,這個(gè)進(jìn)程是由于在后臺(tái)嘗試用OpenGL ES 或者 Metal來(lái)渲染,而被殺掉的。See QA1766: How to fix OpenGL ES application crashes when moving to the background.
3.用地址消毒劑(Address Sanitizer,這是xcode7引入的新特性 )來(lái)跑程序。
The address sanitizer adds additional instrumentation around memory access in your compiled code. As your application runs, Xcode will alert you if memory is accessed in a way that could lead to a crash.
Abnormal Exit (異常退出)[EXC_CRASH // SIGABRT]
進(jìn)程異常退出。該異常類型崩潰最常見(jiàn)的原因是未捕獲的Objective-C和C++異常和調(diào)用abort()。
如果他們需要太多的時(shí)間來(lái)初始化,程序?qū)⒈唤K止,因?yàn)橛|發(fā)了看門(mén)狗。如果是因?yàn)閱?dòng)的時(shí)候被掛起,所產(chǎn)生的崩潰報(bào)告異常類型(Exception Subtype)將是launch_hang。
Trace Trap (追蹤捕獲)[EXC_BREAKPOINT // SIGTRAP]
類似于異常退出,這個(gè)異常是為了給附加的調(diào)試器中斷的過(guò)程的機(jī)會(huì)在其執(zhí)行一個(gè)特定的點(diǎn)。您可以從您自己的代碼引發(fā)此異常使用__builtin_trap()函數(shù)。如果沒(méi)有調(diào)試器連接,進(jìn)程將被終止并生成崩潰報(bào)告。
Illegal Instruction(非法指令) [EXC_BAD_INSTRUCTION // SIGILL]
進(jìn)程試圖執(zhí)行非法或未定義指令。這個(gè)進(jìn)程可能試圖通過(guò)一個(gè)配置錯(cuò)誤的函數(shù)指針,跳到一個(gè)無(wú)效的地址。在英特爾處理器,ud2操作碼造成EXC_BAD_INSTRUCTION異常但通常用于調(diào)試的時(shí)候的追蹤。在英特爾處理器上的swift代碼因?yàn)檫@個(gè)異常類型而被終止,如果在運(yùn)行時(shí)遇到意外情況。有關(guān)詳細(xì)信息,請(qǐng)參閱追蹤捕獲。
Resource Limit [EXC_RESOURCE]
這個(gè)進(jìn)程超出了資源消耗的限制。這是一個(gè)從操作系統(tǒng)通知,進(jìn)程是使用太多的資源。這雖然不是崩潰但也會(huì)生成崩潰日志。
其它的異常信息
0x8badf00d: 讀做 “ate bad food”! (把數(shù)字換成字母,是不是很像 :p)該編碼表示應(yīng)用是因?yàn)榘l(fā)生watchdog超時(shí)而被iOS終止的。 通常是應(yīng)用花費(fèi)太多時(shí)間而無(wú)法啟動(dòng)、終止或響應(yīng)用系統(tǒng)事件。
0xbad22222: 該編碼表示 VoIP 應(yīng)用因?yàn)檫^(guò)于頻繁重啟而被終止。
0xdead10cc: 讀做 “dead lock”!該代碼表明應(yīng)用因?yàn)樵诤笈_(tái)運(yùn)行時(shí)占用系統(tǒng)資源,如通訊錄數(shù)據(jù)庫(kù)不釋放而被終止 。
0xdeadfa11: 讀做 “dead fall”! 該代碼表示應(yīng)用是被用戶強(qiáng)制退出的。根據(jù)蘋(píng)果文檔, 強(qiáng)制退出發(fā)生在用戶長(zhǎng)按開(kāi)關(guān)按鈕直到出現(xiàn) “滑動(dòng)來(lái)關(guān)機(jī)”, 然后長(zhǎng)按 Home按鈕。強(qiáng)制退出將產(chǎn)生 包含0xdeadfa11 異常編碼的崩潰日志, 因?yàn)榇蠖鄶?shù)是強(qiáng)制退出是因?yàn)閼?yīng)用阻塞了界面。
待補(bǔ)充
其它捕捉和符號(hào)化崩潰日志的方法
1.通過(guò)代碼來(lái)捕捉崩潰信息,并發(fā)送到指定的地方
在項(xiàng)目的代碼中重新指定頂層的錯(cuò)誤處理的handler,這樣可以在軟件崩潰前的最后一秒調(diào)用錯(cuò)誤處理的函數(shù)來(lái)獲得崩潰的信息(這里的信息已經(jīng)是被符號(hào)化的)。然后將崩潰信息發(fā)送到自己的服務(wù)器或者其它的地方,以便開(kāi)發(fā)者鞏固自己的代碼的可靠性。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
appDelegate = self;
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
_notification = notification;
NSSetUncaughtExceptionHandler(&caughtExceptionHandler);
/*Changes the top-level error handler.
Sets the top-level error-handling function where you can perform last-minute logging before the program terminates
*/
return YES;
}
void caughtExceptionHandler(NSException *exception){
/**
* 獲取異常崩潰信息
*/
NSArray *callStack = [exception callStackSymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];
NSString *content = [NSString stringWithFormat:@"========異常錯(cuò)誤報(bào)告========\\nname:%@\\nreason:\\n%@\\ncallStackSymbols:\\n%@",name,reason,[callStack componentsJoinedByString:@"\\n"]];
//把異常崩潰信息發(fā)送至開(kāi)發(fā)者郵件
NSMutableString *mailUrl = [NSMutableString string];
[mailUrl appendString:@"mailto:xxx@qq.com"];
[mailUrl appendString:@"?subject=程序異常崩潰信息,請(qǐng)配合發(fā)送異常報(bào)告,謝謝合作!"];
[mailUrl appendFormat:@"&body=%@", content];
// 打開(kāi)地址
NSString *mailPath = [mailUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:mailPath]];
}