Android NDK的调试经验

本文将分享如何在智能语音识别项目中使用NDK进行开发,并通过分析Crashlog来定位和解决问题。包括配置环境、编译SO库、解析Crashlog以及使用arm-linux-androideabi-objdump工具反编译分析具体问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

近期在做智能语音识别的项目,由于涉及到NDK的开发,而之前并没有没有NDK crash log的分析经验,这次积累了一些,分享给大家。

具体的环境搭建想必大家也都知道,详细的配置大家可以问下度娘,这里以我的开发环境来讲下,Eclipse+SDK+NDK(android-ndk-r9d)。

这里把NDK的编译配置也讲一下,以免有人走弯路。
1、打开配置面板。项目右键 -> Properties
这里写图片描述

2、新建编译器。Builders -> New… -> Program

Tab菜单 -> Main ->
Browse File System… 选择ndk目录下ndk-build.cmd文件
Browse Workspace… 选择需要编译的项目
这里写图片描述

Tab菜单 -> Refresh -> 勾选Refresh resources upon completion.
这里写图片描述

Tab菜单 -> Build Options ->
勾选During Auto builds
勾选Specify working set of relevant resources
这里写图片描述

点击Specify Resources… 选择需要编译的项目下的jni目录
这里写图片描述

到此,NDK编译配置就完成了,现在就可以编译你的NDK了。
这里写图片描述

在编译SO成功时,大家有没有注意到在项目根目录下,有个obj目录,这里存放的都是此次编译的中间文件,虽然不会编译进APK里,但调试时会用到。
这里写图片描述

一切都是准备工作,真正分析Crash log才刚刚开始,下边就以我在实际当中遇到的一个log为例。包名和SO名称以及经过处理,可以忽略。

pid: 22258, tid: 2156  >>> com.package <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000014
 r0 68ef9718  r1 00000018  r2 00000014  r3 00000000
 r4 00000200  r5 6d35b008  r6 00000019  r7 00000003
 r8 7587dc78  r9 6ad3bf18  10 7a6fa568  fp 7587dc8c
 ip 00000000  sp 7587db88  lr 6ad1241d  pc 6ad1248c  cpsr 20000030
         #00  pc 0001248c  /data/data/com.package/lib/libXXXSpeechSDK.so
         #01  pc 000134ca  /data/data/com.package/lib/libXXXSpeechSDK.so
         #02  pc 00010e32  /data/data/com.package/lib/libXXXSpeechSDK.so
         #03  pc 00012b5a  /data/data/com.package/lib/libXXXSpeechSDK.so
         #04  pc 00012c4e  /data/data/com.package/lib/libXXXSpeechSDK.so
         #05  pc 0001370e  /data/data/com.package/lib/libXXXSpeechSDK.so
         #06  pc 0001fb70  /system/lib/libdvm.so
         #07  pc 0004e8ba  /system/lib/libdvm.so
         #08  pc 00029020  /system/lib/libdvm.so
         #09  pc 0002d7e8  /system/lib/libdvm.so
         #10  pc 0005ff32  /system/lib/libdvm.so
         #11  pc 0005ff5a  /system/lib/libdvm.so
         #12  pc 0005535a  /system/lib/libdvm.so
         #13  pc 00012ff0  /system/lib/libc.so
         #14  pc 00012748  /system/lib/libc.so

         >>> [translate by crash parser] <<<
         #00  pc 0001248c  /data/data/com.package/lib/libXXXSpeechSDK.so
         #01  pc 000134ca  /data/data/com.package/lib/libXXXSpeechSDK.so
         #02  pc 00010e32  /data/data/com.package/lib/libXXXSpeechSDK.so
         #03  pc 00012b5a  /data/data/com.package/lib/libXXXSpeechSDK.so
         #04  pc 00012c4e  /data/data/com.package/lib/libXXXSpeechSDK.so
         #05  pc 0001370e  /data/data/com.package/lib/libXXXSpeechSDK.so
         #06  pc 0001fb70  /system/lib/libdvm.so
         #07  pc 0004e8ba  /system/lib/libdvm.so
         #08  pc 00029020  /system/lib/libdvm.so
         #09  pc 0002d7e8  /system/lib/libdvm.so
         #10  pc 0005ff32  /system/lib/libdvm.so
         #11  pc 0005ff5a  /system/lib/libdvm.so
         #12  pc 0005535a  /system/lib/libdvm.so
         #13  pc 00012ff0  /system/lib/libc.so
         #14  pc 00012748  /system/lib/libc.so

         >>> [Dalvik stack info] <<<

code around pc:
6ad1246c: 310150c2 3304692c 42a16ae8 f7ffddf8  .P.1,i.3.j.B....
6ad1247c: 696ffd59 e04f00f9 99026aeb 3a04185a  Y.oi..O..j..Z..:
6ad1248c: 9a026811 589c1c08 2b006b2b f00cd00b  .h.....X+k.+....
6ad1249c: 1c21eb4e 1c201c06 eb48f00c 1c301c01  N.!... ...H...0.
6ad124ac: ea22f00c f00ce010 1c21eb42 1c201c06  ..".....B.!... .

code around lr:
6ad123fc: eecef00b 1c049e08 68b01c0d eec8f00b  ...........h....
6ad1240c: 1c0b1c02 1c291c20 ed46f00b ea16f00c  .... .)...F.....
6ad1241c: b0252300 60b36070 46c0bdf0 00000000  .#%.p`.`...F....
6ad1242c: 3fe00000 b087b5f0 31049104 91011c15  ...?.......1....
6ad1243c: 23011c0a e0012100 3301c202 42a368ac  ...#.!.....3.h.B

stack:
7587db48:  f7a3667e 3f992155 60000000 c07249a2 
7587db58:  68ef9b2c 00000800 00000080 00000000 
7587db68:  00000080 000001ff 00000190 00000200 
7587db78:  6d35b008 00000019 e3a070ad ef9000ad 
7587db88:  65e677ed 691b8444 00000018 6ad11f2b   #sp
7587db98:  691b8440 68d64898 00000190 6d35b008 
7587dba8:  68d64898 00000019 740efb60 6ad134cf 
7587dbb8:  00000001 691b8440 00000000 00000003 
7587dbc8:  00000190 0000001a 00000016 721c9e78 
7587dbd8:  00000001 7217f720 0000000e 686cf3c8 
7587dbe8:  00003e80 6ad10e37 686cf3c8 77ab0308 
7587dbf8:  6ad10e1f 68ce5d90 7587dc5c 6ad12b5d 
7587dc08:  0000000e 68ce5d90 7587dc58 6ad12c53 
7587dc18:  7587dc34 436e0550 00003e80 00003e7f 
7587dc28:  77aae008 0000f9fc 6ad2a820 6ad12ba1 
7587dc38:  6ad22e0d 00000000 00003e80 6ad13711 
7587dc48:  7587dc58 00000000 41317578 436d8850 
7587dc58:  00000000 00000000 436d8840 62cf59d0 
7587dc68:  7a6fa558 00000004 6ad3bf20 41288b74 
7587dc78:  6ad3bf14 00000001 42a2fd68 6aee02d1 
7587dc88:  00000000 412b78bd 6ad3bf14 6aee02ce 
7587dc98:  6ad136a9 7a6fa568 00000000 00000000 
7587dca8:  00000001 401dca6c 42dc8c00 42dc8c00 
7587dcb8:  00000001 42128018 43585e88 43585e88 
7587dcc8:  7a6fa8c4 43585e88 00000003 7a6fa558 
7587dcd8:  0000004c 43585e88 00000000 412be98d 
7587dce8:  7587dd54 626cc9dc 00000001 4160c6c0 
7587dcf8:  00000001 42128018 439d7af0 439d7af0 
7587dd08:  42128018 00010fce 00000001 4022766b 
7587dd18:  4008f008 413192c0 439d7af0 412d75b5 
7587dd28:  413178e8 41317578 00010fce 00000000 
7587dd38:  41317578 41295338 7587dd54 f79ebef4 
7587dd48:  7587dd54 415a87d8 00010fbe 00000000 
7587dd58:  401dca6c 412d0625 42a5d97c 6ad3beec 
7587dd68:  1dcd64ff 412bc109 7a6fa558 f79ebef4 
7587dd78:  00000001 6aede5b8 6ad3bf34 7a6fa558 
7587dd88:  42d09e40 41288d00 00000000 6ad3bf00 
7587dd98:  00000000 41292024 00000000 7a6fa558 
7587dda8:  41311c5c 627d2628 00000000 7587ddd4 
7587ddb8:  7587deb0 00000000 00000000 412967ec 
7587ddc8:  00000000 00000000 00000000 00000000 
7587ddd8:  6ad3bfe4 00000000 00000000 00000000 
7587dde8:  00000000 00000000 00000000 00000000 
7587ddf8:  00000000 00000000 00000000 44340000 
7587de08:  44a00000 42400000 00000000 00000000 
7587de18:  42400000 42400000 3f7ff797 3f000000 
7587de28:  3f7ff797 e5caa992 fbfbfbfb fbfbfbfb 
7587de38:  7a6fa558 627d2628 7587dea8 427c4008 
7587de48:  6ad3bfec 642a5a18 7587deb0 412c8f35 
7587de58:  7a6fa558 627d2628 427c4008 7587deb0 
7587de68:  412f9b22 401dca6c 627d2628 41317874 
7587de78:  00100000 7a6fa558 00000001 412c8f5f 
7587de88:  7587deb0 7587dea8 7a6fa558 7587dea8 
7587de98:  401dca6c 7a6fa558 412be35f 7587deb0 
7587dea8:  71e89d98 00000000 00000000 00000000 
7587deb8:  00000000 71e89db0 00000000 00000000 
7587dec8:  00000000 71e89dad 71e89d98 f79ebef4 
7587ded8:  7587df00 412be289 7a6fa558 00000078 
7587dee8:  412be289 4019eff4 6efd71d0 7587df00 
7587def8:  bef75738 4019e74c 7587df00 6efd71d0 
7587df08:  00000016 00000000 00000000 00000000 
7587df18:  7a6fa558 00000000 00000000 00000000 
7587df28:  00000000 6b93e260 687f6e20 00000000 
7587df38:  00000000 00000000 00000000 00000000 
7587df48:  00000000 00000000 00000000 00000000 
7587df58:  00000000 00000000 00000000 00000000 
7587df68:  00000000 00000000 00000000 00000000 
7587df78:  00000000 00000000 00000000 00000000 
7587df88:  00000000 00000000 00000000 00000000 
7587df98:  00000000 00000000 00000000 00000000 
7587dfa8:  00000000 00000000 00000000 00000000 
7587dfb8:  00000000 00000000 00000000 00000000 
7587dfc8:  00000000 00000000 00000000 00000000 
7587dfd8:  00000000 00000000 00000000 00000000 
7587dfe8:  00000000 00000000 00000000 00000000 
print call stack finish!

获取log的方式不用计较,这是我们对系统log进行过特殊处理获取的。

开发中获取log可以使用

adb logcat -c && adb logcat  > D://crash.log

如果想加过滤可以过滤器
Linux adb logcat -c && adb logcat | find "过滤词" > D://crash.log
Windows adb logcat -c && adb logcat | grep "过滤词" > D://crash.log

libdvm.so是Java层的堆栈关系,可以不用管,本文只分析此次NDK开发的log。

在上述log里,真实的Crash是在这里signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000014
寄存器的位置是00000014,这是个野指针,在log里有指明内存栈的调用,“sp 7587db88”是指从寄存器7587db88开始的,在之后的log里也有输出“7587db88: 65e677ed 691b8444 00000018 6ad11f2b #sp”

我们通过ndk-stack可以把这段log转化成NDK的调用堆栈,注意这里使用的是中间文件下的armeabi目录

D:\WorkStation\install\adt-bundle-windows-x86_64-20140702\android-ndk-r9d>ndk-st
ack -sym E:\WorkPlace\项\obj\local\armeabi -dum
p 转换前日志文件 > 转换后的日志文件

这时候的日志就输出成堆栈的调用情况

********** Crash dump: **********
Build fingerprint: 'Xiaomi/aries/aries:4.1.1/JRO03L/JLB52.0:user/release-keys'
pid: 22258, tid: 2156  >>> com.package <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000014
Stack frame          #00  pc 0001248c  /data/data/com.package/lib/libxxxSpeechSDK.so: Routine Realft(float*) at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/signal_process.cpp:452
Stack frame          #01  pc 000134ca  /data/data/com.package/lib/libxxxSpeechSDK.so: Routine qn_sigmoid_vf_vf at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/QN_fltvec.h:179
Stack frame          #02  pc 00010e32  /data/data/com.package/lib/libxxxSpeechSDK.so: Routine ~CMVNFeatureTranslator at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/feature_translate.cpp:243
Stack frame          #03  pc 00012b5a  /data/data/com.package/lib/libxxxSpeechSDK.so: Routine Vader::Init(char*, char*, char*) at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/vad.cpp:37
Stack frame          #04  pc 00012c4e  /data/data/com.package/lib/libxxxSpeechSDK.so: Routine ~Vader at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/vad.cpp:84
Stack frame          #05  pc 0001370e  /data/data/com.package/lib/libxxxSpeechSDK.so: Routine KillFE(FeOption*) at E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/wav2feat.cpp:115
Stack frame          #06  pc 0001fb70  /system/lib/libdvm.so
Stack frame          #07  pc 0004e8ba  /system/lib/libdvm.so
Stack frame          #08  pc 00029020  /system/lib/libdvm.so
Stack frame          #09  pc 0002d7e8  /system/lib/libdvm.so
Stack frame          #10  pc 0005ff32  /system/lib/libdvm.so
Stack frame          #11  pc 0005ff5a  /system/lib/libdvm.so
Stack frame          #12  pc 0005535a  /system/lib/libdvm.so
Stack frame          #13  pc 00012ff0  /system/lib/libc.so
Stack frame          #14  pc 00012748  /system/lib/libc.so

这个时候就可以根据堆栈分析问题原因了,如果还不够详细,还可以使用arm-linux-androideabi-objdump反编译分析具体哪个指针有问题。

D:\WorkStation\install\adt-bundle-windows-x86_64-20140702\android-ndk-r9d\toolch
ains\arm-linux-androideabi-4.8\prebuilt\windows-x86_64\bin>arm-linux-androideabi
-objdump.exe   -DSl E:\WorkPlace\xxxSpeech\xxxVoiceRecognition\obj\local\a
rmeabi\libxxxSpeechSDK.so > D://core.txt

就可以查看各个文件里每个方法的指针位置,再根据寄存器位置,找到具体有问题的指针。

E:\WorkPlace\xxxSpeech\xxxVoiceRecognition/jni/vad/signal_process.cpp:442
        s[i1] = xr1 + wrs * xr2 - wis * xi2;
   12330:   00000014    andeq   r0, r0, r4, lsl r0
   12334:   14510001    ldrbne  r0, [r1], #-1
   12338:   30000000    andcc   r0, r0, r0
   1233c:   01000000    mrseq   r0, (UNDEF: 0)
   12340:   00305000    eorseq  r5, r0, r0
   12344:   01140000    tsteq   r4, r0
   12348:   00020000    andeq   r0, r2, r0
   1234c:   00006091    muleq   r0, r1, r0
   12350:   00000000    andeq   r0, r0, r0
   12354:   00020000    andeq   r0, r2, r0
   12358:   00180000    andseq  r0, r8, r0
   1235c:   00010000    andeq   r0, r1, r0
   12360:   00001852    andeq   r1, r0, r2, asr r8
   12364:   00009c00    andeq   r9, r0, r0, lsl #24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值