目录
上一篇 深入浅出Android NDK之在jni中使用线程
假设有如下代码,运行到48行时肯定会发生崩溃。
这时候我们查看logcat,会有以下输出:
2019-10-16 11:21:15.943 20250-20250/? I/AEE_AED: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
2019-10-16 11:21:15.943 20250-20250/? I/AEE_AED: Build fingerprint: 'alps/full_mt8167_tb_n/mt8167_tb_n:7/NRD90M/20200325:user/release-keys'
2019-10-16 11:21:15.943 20250-20250/? I/AEE_AED: Revision: '0'
2019-10-16 11:21:15.943 20250-20250/? I/AEE_AED: ABI: 'arm'
2019-10-16 11:21:15.943 20250-20250/? I/AEE_AED: pid: 20225, tid: 20225, name: example.strtest >>> com.example.strtest <<<
2019-10-16 11:21:15.943 20250-20250/? I/AEE_AED: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
2019-10-16 11:21:15.943 20250-20250/? I/AEE_AED: r0 00000000 r1 00000000 r2 00000000 r3 00000000
2019-10-16 11:21:15.943 20250-20250/? I/AEE_AED: r4 e8efe008 r5 e061de35 r6 ff970b88 r7 ff970a98
2019-10-16 11:21:15.944 20250-20250/? I/AEE_AED: r8 ff970de0 r9 e7904400 sl e790448c fp ff970b14
2019-10-16 11:21:15.944 20250-20250/? I/AEE_AED: ip e8ef985c sp ff970a64 lr e061e017 pc e061dfcc cpsr 60070030
2019-10-16 11:21:15.944 801-927/com.android.systemui V/NetworkController: onConfigurationChanged NetWorkControllerImpl
2019-10-16 11:21:15.944 801-927/com.android.systemui D/NetworkController: NETworkController 11
2019-10-16 11:21:15.946 20250-20250/? I/AEE_AED: backtrace:
2019-10-16 11:21:15.946 20250-20250/? I/AEE_AED: #00 pc 00009fcc /data/app/com.example.strtest-1/lib/arm/libstrtest.so
2019-10-16 11:21:15.946 20250-20250/? I/AEE_AED: #01 pc 0000a013 /data/app/com.example.strtest-1/lib/arm/libstrtest.so (Java_com_example_threadtest_PThread_start+62)
2019-10-16 11:21:15.946 20250-20250/? I/AEE_AED: #02 pc 002655d5 /data/app/com.example.strtest-1/oat/arm/base.odex (offset 0x24d000)
通过日志,我们并不知道是哪个函数的那一行发生了崩溃。
我们可以通过ndk-stack命令将十六进制的地址转换为具体的文件名,函数名,行号。
C:\Users\zy>adb logcat|ndk-stack -sym D:\ndk-demo\StrTest\app\build\intermediates\ndkBuild\debug\obj\local\armeabi-v7a
********** Crash dump: **********
Build fingerprint: 'alps/full_mt8167_tb_n/mt8167_tb_n:7/NRD90M/20200325:user/release-keys'
pid: 20225, tid: 20225, name: example.strtest >>> com.example.strtest <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
Stack frame 10-16 11:21:15.946 20250 20250 I AEE_AED : #00 pc 00009fcc /data/app/com.example.strtest-1/lib/arm/libstrtest.so: Routine crash_test() at D:/ndk-demo/StrTest/app/src/main/jni/PThread.cpp:48
Stack frame 10-16 11:21:15.946 20250 20250 I AEE_AED : #01 pc 0000a013 /data/app/com.example.strtest-1/lib/arm/libstrtest.so (Java_com_example_threadtest_PThread_start+62): Routine Java_com_example_threadtest_PThread_start at D:/ndk-demo/StrTest/app/src/main/jni/PThread.cpp:54
Stack frame 10-16 11:21:15.946 20250 20250 I AEE_AED : #02 pc 002655d5 /data/app/com.example.strtest-1/oat/arm/base.odex (offset 0x24d000)
Crash dump is completed
ndk-stack详细用法,请参考官方文档:
https://developer.android.google.cn/ndk/guides/ndk-stack
当程序发生anr时,这时候使用ndk-stack是没办法转换的,因为anr日志格式和崩溃的日志格式不一样,ndk-stack没办法识别,这时候我们可以用addr2line。
C:\Users\zy>D:\android-ndk-r20b\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-addr2line.exe -p -f -C -e D:\ndk-demo\StrTest\app\build\intermediates\ndkBuild\debug\obj\local\armeabi-v7a\libstrtest.so 00009fcc 0000a013
crash_test() at D:/ndk-demo/StrTest/app/src/main/jni/PThread.cpp:48
Java_com_example_threadtest_PThread_start at D:/ndk-demo/StrTest/app/src/main/jni/PThread.cpp:54
不管是ndk-stack还是addr2line都需要符号表,编译的时候在生成SO的同时会生成符号表。所以除了SO以外,符号表也要保存好, 这样发生崩溃的时候才能查找问题。