iOS 開發中常見的錯誤記錄檔處理

來源:互聯網
上載者:User

標籤:

Outline
如何獲得crash日誌
如何解析crash日誌
如何分析crash日誌
     1. iOS策略相關
     2. 常見錯誤標識
     3. 代碼bug


一、如何獲得crash日誌

當一個iOS應用程式崩潰時,系統會建立一份crash日誌儲存在裝置上。這份crash日誌記錄著應用程式崩潰時的資訊,通常包含著每個執行線程的棧調用資訊(低記憶體閃退日誌例外),對於開發人員定位問題很有協助。

如果裝置就在身邊,可以串連裝置,開啟Xcode - Window - Organizer,在左側面板中選擇Device Logs(可以選擇具體裝置的Device Logs或者Library下所有裝置的Device Logs),然後根據時間排序查看裝置上的crash日誌。這是開發、測試階段最經常採用的方式。

如果應用程式已經提交到App Store發布,使用者已經安裝使用了,那麼開發人員可以通過iTunes Connect(Manage Your Applications - View Details - Crash Reports)擷取使用者的crash日誌。不過這並不是100%有效,而且大多數開發人員並不依賴於此,因為這需要使用者裝置同意上傳相關資訊,詳情可參見iOS: Providing Apple with diagnostics and usage information摘要。

考慮到並不是所有iPhone使用者都允許自動發送診斷報告(crash日誌),而且對於部分提交到Apple得crash日誌,開發人員還需要手動去拉取,然後找到對應的符號檔案進行解析——這是一件很繁瑣的事情。所以實際項目開發中,通常接入現有的crash收集工具(參考1,參考2),或者自己編寫一個進行自動化收集、解析和統計匯總。


二、如何解析crash日誌

當獲得一份crash日誌時,我們需要將初始展示的十六進位地址等原始資訊映射為原始碼層級的方法名稱和程式碼數,使其對開發人員可讀。這個過程稱為符號化解析。要成功地符號化解析一份crash日誌,我們需要有對應的應用程式二進位檔案以及符號(.dSYM)檔案。

如果處於開發調試階段,通常Xcode都能匹配到crash日誌對應的二進位檔案和符號檔案,所以能夠幫我們自動解析。

如果處於測試階段,測試人員已經安裝了不同的版本(比如alpha、beta版本),那麼需要儲存好對應版本的二進位檔案和符號檔案,以便在應用程式崩潰時對crash日誌進行解析。對於這種情境下產生的crash日誌,只需要將.crash檔案、.app檔案和.dSYM檔案三者放在同一個目錄下,然後將.crash檔案拖放到Xcode - Window - Organizer中左側面板Library下的Device Logs中,即可進行解析。

如果要提交發布,那麼我們通常會先執行Clean,再Build,最後通過Product - Archive來打包。這樣,Xcode會將二進位檔案和符號檔案歸檔在一起,可以通過Organizer中的Archives進行瀏覽。

這裡是一份關於如何解析crash日誌的討論:http://stackoverflow.com/questions/1460892/symbolicating-iphone-app-crash-reports 。


三、如何分析crash日誌

在分析一份crash日誌之前,如果開發人員對於常見的錯誤類型有所瞭解,那定是極好的。
crash日誌的產生來源於兩種問題:違反iOS策略被幹掉,以及自身的代碼bug。

1. iOS策略

1.1 低記憶體閃退
前面提到大多數crash日誌都包含著執行線程的棧調用資訊,但是低記憶體閃退日誌除外,這裡就先看看低記憶體閃退日誌是什麼樣的。
我們使用Xcode 5和iOS 7的裝置類比一次低記憶體閃退,然後通過Organizer查看產生的crash日誌,可以發現Process和Type都為Unknown:



而具體的日誌內容如下:



第一部分是崩潰資訊,包括識別標識、軟硬體資訊和時間資訊等。
第二部分是記憶體頁分配資訊,以及當前佔用記憶體最多的進程,中為crashTypeDemo。
第三部分是具體的進程列表,描述著每個進程使用記憶體的情況以及目前狀態。在較早的版本中可以在某些進程後面看到“jettisoned”字樣,表明這些進程使用過多記憶體被終止了,而現在我們看到的是“vm-pageshortage”字樣。

當iOS檢測到記憶體過低時,它(的VM系統)會發出低記憶體警告通知,嘗試回收一些記憶體;如果情況沒有得到足夠的改善,iOS會終止後台應用以回收更多記憶體;最後,如果記憶體還是不足,那麼正在啟動並執行應用可能會被終止掉。
所以,我們的應用應該合理地響應系統拋出來的低記憶體警告通知,對一些快取資料和可重新建立的對象進行釋放,同時要避免出現記憶體泄露等問題。

低記憶體閃退是由iOS策略決定終止應用程式啟動並執行,同樣基於iOS策略的還有Watchdog逾時和使用者強制退出。

1.2 Watchdog逾時
Apple的iOS Developer Library網站上,QA1693文檔中描述了Watchdog機制,包括生效情境和表現。如果我們的應用程式對一些特定的UI事件(比如啟動、掛起、恢複、結束)響應不及時,Watchdog會把我們的應用程式幹掉,並產生一份響應的crash報告。

這份crash報告的有趣之處在於異常代碼:“0x8badf00d”,即“ate bad food”。
如果說特定的UI事件比較抽象,那麼用代碼來直接描述的話,對應的就是(建立一個工程時Xcode自動產生的)UIApplicationDelegate的幾個方法:



所以當遇到Watchdog日誌時,可以檢查下幾個方法是否有比較重的阻塞UI的動作。

QA1693舉的例子是在主線程進行同步網路請求。如果我們是在公司的Wifi環境下使用則一切順利,但當應用程式發布出去面向很大範圍的使用者,在各種網路環境下運行,則不可避免地會出現一片Watchdog逾時報告。
另一種可能出現問題的情境就是資料量比較大的情況下進行的資料庫版本遷移(同樣是在主線程上),這也是促使我寫這篇總結的一個直接因素。

1.3 使用者強制退出

一看到“使用者強制退出”,首先可能想到的雙擊Home鍵,然後關閉應用程式。不過這種情境是不會產生crash日誌的,因為雙擊Home鍵後,所有的應用程式都處於後台狀態,而iOS隨時都有可能關閉後台進程,所以這種情境沒有crash日誌。

另一種情境是使用者同時按住電源鍵和Home鍵,讓iPhone重啟。這種情境會產生日誌(僅驗證過一次),但並不針對特定應用程式。

這裡指的“使用者強制退出”情境,是稍微比較複雜點的操作:先按住電源鍵,直到出現“滑動關機”的介面時,再按住Home鍵,這時候當前應用程式會被終止掉,並且產生一份相應事件的crash日誌。



通常,使用者應該是遇到應用程式卡死,並且影響到了iOS響應,才會進行這樣的操作——不過感覺這操作好進階,所以這樣的crash日誌應該比較少見。

2. 常見錯誤標識

2.1 Exception codes
上面“使用者強制退出”的crash日誌中的Exception Codes是“0xdeadfa11”,再上面“Watchdog逾時”的crash日誌中的Exception Codes是“0x8badf00d”,這些都是特有的Exception codes。
根據官方文檔描述,至少有以下幾種特定異常代碼:

0x8badf00d錯誤碼:Watchdog逾時,意為“ate bad food”。

0xdeadfa11錯誤碼:使用者強制退出,意為“dead fall”。

0xbaaaaaad錯誤碼:使用者按住Home鍵和音量鍵,擷取當前記憶體狀態,不代表崩潰。



0xbad22222錯誤碼:VoIP應用(因為太頻繁?)被iOS幹掉。

0xc00010ff錯誤碼:因為太燙了被幹掉,意為“cool off”。

0xdead10cc錯誤碼:因為在後台時仍然佔據系統資源(比如通訊錄)被幹掉,意為“dead lock”。

2.2 Exception types
查看我們的crash分析報告郵件,會發現最經常遇到的錯誤類型是SEGV(Segmentation Violation,段違例),表明記憶體操作不當,比如訪問一個沒有許可權的記憶體位址。
當我們收到SIGSEGV訊號時,可以往以下幾個方面考慮:
訪問無效記憶體位址,比如訪問Zombie對象;
嘗試往唯讀地區寫資料;
解引用null 指標;
使用未初始化的指標;
棧溢出;
此外,還有其它常見訊號:
SIGABRT:收到Abort訊號,可能自身調用abort()或者收到外部發送過來的訊號;
SIGBUS:匯流排錯誤。與SIGSEGV不同的是,SIGSEGV訪問的是無效地址(比如虛存映射不到實體記憶體),而SIGBUS訪問的是有效地址,但匯流排訪問異常(比如地址對齊問題);
SIGILL:嘗試執行非法的指令,可能不被識別或者沒有許可權;
SIGFPE:Floating Point Error,數學計算相關問題(可能不限於浮點計算),比如除零操作;
SIGPIPE:管道另一端沒有進程接手資料;

3. 代碼bug
此外,比較常見的崩潰基本都源於代碼bug,比如數組越界、插空、多執行緒安全性、訪問野指標、發送未實現的selector等。如果引入Core Data,則又有另外一些常見問題,不過這是另一個話題了。

遇到這些bug時,都有比較清楚的錯誤原因說明,比如“index 0 beyond bounds for empty array”等。需要稍微注意點的是多線程問題,當一時找不到解決思路時,不妨往多線程方面考慮下

iOS 開發中常見的錯誤記錄檔處理

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.