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

相关文章
相关标签/搜索