NDK學習-指南(三)

Android NDK Tombstone/Crash 分析

##Android 開發中常見 Crash 的狀況android

在 Android 開發中,程序 Crash 分三種狀況:程序員

  • 未捕獲的異常
  • ANR(Application Not Responding)
  • 閃退(NDK 程序引起錯誤)

其中未捕獲的異常根據 logcat 打印的堆棧信息很容易定位錯誤。bash

ANR錯誤也好查,Android規定,應用與用戶進行交互時,若是5秒內沒有響應用戶的操做,則會引起ANR錯誤,並彈出一個系統提示框,讓用戶選擇繼續等待或當即關閉程序。並會在/data/anr目錄下生成一個traces.txt文件,記錄系統產生anr異常的堆棧和線程信息。composer

若是是閃退,這問題比較難查,一般是項目中用到了 NDK 引起某類致命的錯誤致使閃退。由於 NDK 是使用 C/C++ 來進行開發,熟悉 C/C++ 的程序員都知道,指針和內存管理是最重要也是最容易出問題的地方,稍有不慎就會遇到諸如內存地址訪問錯誤、使用野指針、內存泄露、堆棧溢出、初始化錯誤、類型轉換錯誤、數字除0等常見的問題,致使最後都是同一個結果:程序崩潰。它不會像在 Java 層產生的異常時彈出「xxx程序無響應,是否當即關閉」之類的提示框。當發生 NDK 錯誤後,logcat 打印出來的那堆日誌根據看不懂,更別想從日誌當中定位錯誤的根源。xss

首先,當 NDK 程序在發生 Crash 時,它會在路徑 /data/tombstones/ 下產生致使程序 Crash 的文件 tombstone_xx。而且 Google 還在 NDK 包中爲咱們提供了一系列的調試工具,例如 addr2lineobjdumpndk-stackide

##Linux 信號機制函數

在介紹 Tombstone 以前,咱們首先補充一個 Linux 信號機制的知識。工具

信號機制是 Linux 進程間通訊的一種重要方式,Linux 信號一方面用於正常的進程間通訊和同步,如任務控制(SIGINT, SIGTSTP,SIGKILL, SIGCONT,……);另外一方面,它還負責監控系統異常及中斷。 當應用程序運行異常時, Linux 內核將產生錯誤信號並通知當前進程。 當前進程在接收到該錯誤信號後,能夠有三種不一樣的處理方式。oop

  • 忽略該信號。
  • 捕捉該信號並執行對應的信號處理函數(signal handler)。
  • 執行該信號的缺省操做(如 SIGSEGV, 其缺省操做是終止進程)。

當 Linux 應用程序在執行時發生嚴重錯誤,通常會致使程序 crash。其中,Linux 專門提供了一類 crash 信號,在程序接收到此類信號時,缺省操做是將 crash 的現場信息記錄到 core 文件,而後終止進程。ui

Crash 信號列表:

Signal Description
SIGSEGV Invalid memory reference.
SIGBUS Access to an undefined portion of a memory object.
SIGFPE Arithmetic operation error, like divide by zero.
SIGILL Illegal instruction, like execute garbage or a privileged instruction
SIGSYS Bad system call.
SIGXCPU CPU time limit exceeded.
SIGXFSZ File size limit exceeded.

##Tombstone

Android Native 程序本質上就是一個 Linux 程序,所以當它在執行時發生嚴重錯誤,也會致使程序 crash,而後產生一個記錄 crash 的現場信息的文件,而這個文件在 Android 系統中就是 tombstone 文件。tombstone 文件位於路徑 /data/tombstones/

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Android-x86/android_x86/x86:5.1.1/LMY48W/woshijpf04211939:eng/test-keys'
Revision: '0'
ABI: 'x86'
pid: 1019, tid: 1019, name: surfaceflinger  >>> /system/bin/surfaceflinger <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4
    eax a6265c06  ebx b7467d88  ecx b7631a22  edx a6265c06
    esi 00000000  edi b6867140
    xcs 00000073  xds 0000007b  xes 0000007b  xfs 00000000  xss 0000007b
    eip b745a639  ebp bfcfc1e8  esp bfcfc150  flags 00010282

backtrace:
    #00 pc 00006639  /system/lib/libui.so (android::Fence::waitForever(char const*)+41)
    #01 pc 00034b86  /system/lib/libsurfaceflinger.so
    #02 pc 0003229e  /system/lib/libsurfaceflinger.so
    #03 pc 0002cb9c  /system/lib/libgui.so (android::BufferQueue::ProxyConsumerListener::onFrameAvailable(android::BufferItem const&)+652)
    #04 pc 000342f4  /system/lib/libgui.so (android::BufferQueueProducer::queueBuffer(int, android::IGraphicBufferProducer::QueueBufferInput const&, android::IGraphicBufferProducer::QueueBufferOutput*)+2580)
    #05 pc 0004eafb  /system/lib/libgui.so (android::Surface::queueBuffer(ANativeWindowBuffer*, int)+411)
    #06 pc 0004ce06  /system/lib/libgui.so (android::Surface::hook_queueBuffer(ANativeWindow*, ANativeWindowBuffer*, int)+38)
    #07 pc 00014bc6  /system/lib/egl/libGLES_android.so
    #08 pc 00017f73  /system/lib/egl/libGLES_android.so (eglSwapBuffers+163)
    #09 pc 00015fdb  /system/lib/libEGL.so (eglSwapBuffers+203)
    #10 pc 000013ea  /system/lib/hw/hwcomposer.x86.so
    #11 pc 00034730  /system/lib/libsurfaceflinger.so
    #12 pc 000256d4  /system/lib/libsurfaceflinger.so
    #13 pc 00024bf4  /system/lib/libsurfaceflinger.so
    #14 pc 000236fb  /system/lib/libsurfaceflinger.so
    #15 pc 0002338a  /system/lib/libsurfaceflinger.so
    #16 pc 0001e0ff  /system/lib/libsurfaceflinger.so
    #17 pc 0001d9ce  /system/lib/libutils.so (android::Looper::pollInner(int)+926)
    #18 pc 0001db73  /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+67)
    #19 pc 0001e561  /system/lib/libsurfaceflinger.so
    #20 pc 00022ce7  /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::run()+39)
    #21 pc 00000ca3  /system/bin/surfaceflinger
    #22 pc 0001365a  /system/lib/libc.so (__libc_init+106)
    #23 pc 00000da8  /system/bin/surfaceflinger

stack:
         bfcfc110  00000000  
         bfcfc114  b6839270  
         bfcfc118  00000000  
         bfcfc11c  00000000  
         bfcfc120  b68394e0  
         bfcfc124  00000002  
         bfcfc128  00000002  
         bfcfc12c  b75d8185  /system/lib/libutils.so (android::RefBase::incStrong(void const*) const+53)
         bfcfc130  b6839270  
         bfcfc134  bfcfc1e8  [stack]
         bfcfc138  00000002  
         bfcfc13c  a6265c06  
         bfcfc140  b7467d88  /system/lib/libui.so
         bfcfc144  00000000  
         bfcfc148  b6867140  
         bfcfc14c  b745a639  /system/lib/libui.so (android::Fence::waitForever(char const*)+41)
    #00  bfcfc150  b683af18  
         bfcfc154  bfcfc1e8  [stack]
         bfcfc158  00000000  
         bfcfc15c  00000000  
         bfcfc160  00000000  
         bfcfc164  b683af18  
         bfcfc168  b75ec9c4  /system/lib/libutils.so
         bfcfc16c  b75d8285  /system/lib/libutils.so (android::RefBase::weakref_type::decWeak(void const*)+37)
         bfcfc170  00000000  
         bfcfc174  00000000  
         bfcfc178  00000000  
         bfcfc17c  00000000  
         bfcfc180  b7642968  /system/lib/libsurfaceflinger.so
         bfcfc184  bfcfc1e8  [stack]
         bfcfc188  b6867140  
         bfcfc18c  b7622b87  /system/lib/libsurfaceflinger.so
複製代碼

tombstone 文件解析

tombstone 文件它主要由下面幾部分組成:

  • Build fingerprint
  • Crashed process and PIDs
  • Terminated signal and fault address
  • CPU registers
  • Call stack
  • Stack content of each call
pid: 1019, tid: 1019, name: surfaceflinger  >>> /system/bin/surfaceflinger <<<
若是 pid 等於 tid ,那麼就說明這個程序是在主線程中 Crash 掉的,name 的屬性則表示 Crash 進程的名稱以及在文件系統中位置。
複製代碼
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4
進程 Crash 的緣由是由於程序產生了段錯誤的信號,訪問了非法的內存空間,而訪問的非法地址是 0x4。
複製代碼

定位 Crash 源碼位置的工具

  • addr2line addr2line -f -e libui.so 00006639

  • ndk-stack ndk-stack -sym obj/local/x86/ -dump ~/android-x86-debug-log/tombstone_01

  • objdump objdump -S -D libc.so > deassmble_libc.txt

    ## 源碼快讀
    複製代碼

bengin: com.android.server.am.ActivityManagerService.startObservingNativeCrashes

相關文章
相關標籤/搜索