標籤:android ndk debug
我們知道 android NDK 程式在崩潰時會產生一個 tombstone 的 backtrace (也可利用 ADB logcat 抓取),從這個 backtrace 中我們可以瞭解是哪個函數引發的崩潰,但是通常由於我們發布時都是 release 版,無法利用 backtrace 中的地址資訊直接定位到源碼和行號,當引發崩潰的錯誤不是很明顯時,對於我們解決問題的協助就不大。
這時通常我們是重編一個 debug 版本並設法重現 crash。這樣做有個兩個問題,一是如果我們不知道複現步驟,或者複現機率很低時,效率不高;二是我們不一定總能滿足 crash 產生的條件,而一旦版本發布後,使用 debug 版本去替換使用者情境中的 release 版又非常麻煩(甚至可能無法實現)。
事實上,有一個辦法可以解決這個問題。我們知道,release 版本的庫檔案也是有 DYNAMIC SYMBOL TABLE 的,你可以使用命令 objdump -T -R <your so> (並重新導向到一個文字檔中)來查看,然後你可以用同樣的命令去查看 debug 版本的 DYNAMIC SYMBOL TABLE,通過比較,不難發現,他們的格式是一樣的,你需要關注的只是第一列(symbol address)和最後一列(symbol name)。
接下來,你在 debug 版本的 DYNAMIC SYMBOL TABLE 中搜尋引發崩潰的函數名,並記下它的 symbol address,然後,你只需要在這個地址上增加一個位移量,就可以使用 addr2line 命令來定位源碼和行號了。這個位移量是多少?請注意 backtrace 中 #00 pc 的最後一列(使用括弧括住),其中在函數名的後面有一個+N,這個N就是崩潰位置的位移量(注意它是10進位數,而 symbol address 是16進位數,你需要先做轉換才能相加)。
需要說明的是,由於 release 版通常都經過了最佳化,backtrace 中的位移量並不一定非常準確,但離實際值差得不會太遠,你可以使用 debug 版做一個對比測試就可以驗證。現在你可以去試試這個方法了,希望這個方法能協助你提高解決 crash 問題的效率。