一.前言
在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;
}