Android NDK开发崩溃 signal 11 (SIGSEGV), code 1 (SEGV_MAPERR),解决方法
一.前言
在NDK开发的过程中,如果遇到应用Crash,JNI层的报错信息并不像java层那样可以看到详细的错误信息和错误位置,如果要想定位到错误位置,需要借助NDK的一些工具进行地址转换,本文中用addr2line(NDK的工具)来捕捉错误信息
二.分析
以下是我的报错信息
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
Cause: null pointer dereference
r0 00000000 r1 e4a9b9dc r2 0000ffff r3 bf1acf00
r4 bf1acf00 r5 bd10da00 r6 bd10da20 r7 00000004
r8 bda55fe0 r9 00000000 r10 bd10dbcc r11 bbdc3858
ip e4dfdfe4 sp bbdc3698 lr e4dfcd83 pc bee6ec34
backtrace:
#00 pc 00011c34 /data/app/com.raypai.splitassist-dqx6PtGtLxCC3HigSgunAA==/lib/arm/libusb100.so
#01 pc 0000d200 /data/app/com.raypai.splitassist-dqx6PtGtLxCC3HigSgunAA==/lib/arm/libusb100.so
#02 pc 0000cb60 /data/app/com.raypai.splitassist-dqx6PtGtLxCC3HigSgunAA==/lib/arm/libusb100.so (libusb_handle_events_timeout_completed+968)
#03 pc 0000d3cc /data/app/com.raypai.splitassist-dqx6PtGtLxCC3HigSgunAA==/lib/arm/libusb100.so (libusb_handle_events+52)
#04 pc 00012c20 /data/app/com.raypai.splitassist-dqx6PtGtLxCC3HigSgunAA==/lib/arm/libuvc.so (_uvc_handle_events+136)
#05 pc 00065ac7 /system/lib/libc.so (__pthread_start(void*)+22)
#06 pc 0001e9ad /system/lib/libc.so (__start_thread+32)
读取其中的关键信息
1.错误代号:Fatal signal 11 (SIGSEGV), code 1,一般都是空指针错误
2.错误发生所在的so文件:libusb100.so
3.错误发生的内存地址:00011c34,不能直接看到源代码发生错误的位置,所以需要用addr2line工具来定位
tip: 1,注意调试文件的位置在obj目录下,并非libs目录下生成的so文件
三.利用addr2line定位错误
- 其中-C -f :表示打印错误行数所在的函数名称,-e:表示打印错误地址的对应路径及行数
- Enter执行,得到结果如下
addr2line -i -C -f -e libusb100.so 00011c34
handle_iso_completion
libusb/os/android_usbfs.c:2729
reap_for_handle
libusb/os/android_usbfs.c:2932
op_handle_events
libusb/os/android_usbfs.c:2990
到这里就可以明确地看到出错误发生在源代码的哪一行了
### 四.后记
通过上面的定位,问题在libusb/os/android_usbfs.c文件中的handle_iso_completion 函数,2729行。
if (urb == tpriv->iso_urbs[i]) {
urb_idx = i + 1;
break;
}
这里tpriv->iso_urbs会有为NULL的时候。从而导致了空指针。
修改方法如下:
if (tpriv->iso_urbs != NULL && urb == tpriv->iso_urbs[i]) {
urb_idx = i + 1;
break;
}