C/C++教程

Android Native Error / Crash 开发时调试分析

本文主要是介绍Android Native Error / Crash 开发时调试分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、前言

这篇文章咱们来看看 Android Native Error / Crash 的问题在开发时如何调试分析。当然只要能分析出原因自然就知道如何去解决啦。

二、问题分析过程

下面的代码在运行时必然发生空指针 NULL 异常从而 引发 App Native Crash。

char *p = NULL;
char c = *p;

本地 / 开发时调试很明显就是我们在开发时遇到程序发生的崩溃或者这是一个可以复现的问题。当然也假设这个 so 是我们自己的。那么这个时候我们的 so 是 unstripped (未剥离版共享库)简单来说就是带有 debug 时的符号表。

下面我们先来看一下上面的代码在发生异常时其报错的大致异常 log 会是怎么样的。

--------- beginning of crash
02-17 23:05:30.893  2610  2610 F libc    : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 2610 (ly.com.crash)
02-17 23:05:30.998  1297  1297 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
02-17 23:05:30.999  1297  1297 F DEBUG   : Build fingerprint: 'Android/sdk_phone_x86_64/generic_x86_64:6.0/MASTER/4174734:userdebug/test-keys'
02-17 23:05:30.999  1297  1297 F DEBUG   : Revision: '0'
02-17 23:05:30.999  1297  1297 F DEBUG   : ABI: 'x86_64'
02-17 23:05:30.999  1297  1297 F DEBUG   : pid: 2610, tid: 2610, name: ly.com.crash  >>> ly.com.crash <<<
02-17 23:05:30.999  1297  1297 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
02-17 23:05:31.003  1297  1297 F DEBUG   :     rax 0000000000000000  rbx 0000000012c53500  rcx 0000000000000000  rdx 000000000000000e
02-17 23:05:31.003  1297  1297 F DEBUG   :     rsi 00007fffbd76dee7  rdi 00007fffbd76df8f
02-17 23:05:31.003  1297  1297 F DEBUG   :     r8  0000000070799dd8  r9  0000000071d8c3b0  r10 00007fffbd76db80  r11 00007f722f0b21a0
02-17 23:05:31.003  1297  1297 F DEBUG   :     r12 0000000000000000  r13 0000000012cba100  r14 0000000012c53500  r15 0000000012c82100
02-17 23:05:31.003  1297  1297 F DEBUG   :     cs  0000000000000033  ss  000000000000002b
02-17 23:05:31.003  1297  1297 F DEBUG   :     rip 00007f722f0b21e0  rbp 00007fffbd76dfa0  rsp 00007fffbd76df30  eflags 0000000000010202
02-17 23:05:31.004  1297  1297 F DEBUG   : 
02-17 23:05:31.004  1297  1297 F DEBUG   : backtrace:
02-17 23:05:31.004  1297  1297 F DEBUG   :     #00 pc 000000000000f1e0  /data/app/ly.com.crash-1/lib/x86_64/libnative-lib.so (Java_ly_com_crash_MainActivity_stringFromJNI+64)
02-17 23:05:31.004  1297  1297 F DEBUG   :     #01 pc 000000000070ba69  /data/app/ly.com.crash-1/oat/x86_64/base.odex (offset 0x2e2000) (java.lang.String ly.com.crash.MainActivity.stringFromJNI()+157)
02-17 23:05:31.004  1297  1297 F DEBUG   :     #02 pc 000000000070b950  /data/app/ly.com.crash-1/oat/x86_64/base.odex (offset 0x2e2000) (void ly.com.crash.MainActivity.onCreate(android.os.Bundle)+228)
02-17 23:05:31.004  1297  1297 F DEBUG   :     #03 pc 00000000734ab4bc  /data/dalvik-cache/x86_64/system@framework@boot.oat (offset 0x1ed6000)
02-17 23:05:31.040  1297  1297 F DEBUG   : 
02-17 23:05:31.040  1297  1297 F DEBUG   : Tombstone written to: /data/tombstones/tombstone_00
02-17 23:05:31.040  1297  1297 E DEBUG   : AM write failed: Broken pipe

这个错误堆栈是从 logcat 里面获取的其崩溃信息已经相对完善了。而且其中还有一句告知了更详细的崩溃日志被写入到了 /data/tombstones/tombstone_00。我们可以借助这个 /data/tombstones/tombstone_00 作更详尽的分析。

然后针对这个错误。从它的 backtrace 中我们可以看到其异常发生在我们自己的 native-lib.so 中了发生异常的错误栈为

 #00 pc 000000000000f1e0  /data/app/ly.com.crash-2/lib/x86_64/libnative-lib.so (Java_ly_com_crash_MainActivity_stringFromJNI+64)

在 Android NDK 中给我们提供了一个工具 ndk-stack 利用 ndk-stack 就可以轻松的将上面的异常栈转换成可定位到源码具体位置的可读性更强的异常栈。

使用 ndk-stack 时我们除了需要包含出问题时的异常栈的 log 之外我们还需要通过参数 -sym 来指定一个 unstripped 的 .so。一般在开发时这个 so 的位置可能如下

  1. 如果你使用的是 ndk-build 来编译的话它可能位于
$PROJECT_PATH/app/build/intermediates/ndk-build/debug/obj/x86_64/***.so

  1. 如果使用的是 cmake 来编译的话它可能位于
$PROJECT_PATH/app/build/intermediates/cmake/debug/obj/x86_64/***.so

而对于指定异常 log 的方式ndk-stack 也提供了两种方式

  1. 将 logcat 直接作为输入
adb logcat | ndk-stack -sym $PROJECT_PATH/app/build/intermediates/cmake/debug/obj/x86_64

  1. 通过 -dump 指定一个包含异常日志的文件
ndk-stack -sym $PROJECT_PATH/app/build/intermediates/cmake/debug/obj/x86_64 -dump foo.txt

上面的 $PROJECT_PATH 你需要替换成你自己的工程绝对路径。

就这样通过上面一顿猛如虎的操作之后我们可以得到异常栈转换后的可读性更强的栈

#00 0x000000000000f1e0 /data/app/ly.com.crash-2/lib/x86_64/libnative-lib.so (Java_ly_com_crash_MainActivity_stringFromJNI+64)
                                                                             Java_ly_com_crash_MainActivity_stringFromJNI
                                                                             /Users/ly/github/HelloCrash/app/src/main/cpp/native-lib.cpp:10:14

可以看到发生异常的地方在 native-lib.cpp 的 第 10 行第 14 列。

三、总结

针对开发时所发生的 native crash 来分析还是很简单的。那么当我们的应用打成 release 包之后发布线上之后又该如何分析呢

点击查看更多内容
这篇关于Android Native Error / Crash 开发时调试分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!