出现问题
Android在开发native层代码是时很容易报 signal 11 (SIGSEGV)
错误,这种问题单看报错日志是很难定位到问题的。比如如下错误是我在开发过程中遇到的,Android Studio也不知道抽什么风断点调试也不能用,好在之前听说过 addr2line
这个工具,但一直没有用过,没办法只好用这个工具试试。
2022-06-21 15:38:00.197 27730-27790/com.jk.superplayer A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x720064 in tid 27790 (Thread-3), pid 27730 (.jk.superplayer)
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: Build fingerprint: 'xiaomi/lavender/lavender:10/QKQ1.190910.002/V12.0.2.0.QFGCNXM:user/release-keys'
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: Revision: '0'
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: ABI: 'arm'
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: Timestamp: 2022-06-21 15:38:00+0800
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: pid: 27730, tid: 27790, name: Thread-3 >>> com.jk.superplayer <<<
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: uid: 10731
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x720064
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: r0 c2e0d400 r1 000002d0 r2 00000500 r3 00000b40
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: r4 c370b1e4 r5 0000001a r6 c370b230 r7 c370b200
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: r8 eec83a50 r9 00006c8c r10 c370b230 r11 00101000
2022-06-21 15:38:00.262 27798-27798/? A/DEBUG: ip 00720065 sp c370b190 lr c39ec9a9 pc 00720064
2022-06-21 15:38:00.264 27798-27798/? A/DEBUG: backtrace:
2022-06-21 15:38:00.264 27798-27798/? A/DEBUG: #00 pc 00720064 <unknown>
2022-06-21 15:38:00.264 27798-27798/? A/DEBUG: #01 pc 000db9a7 /data/app/com.jk.superplayer-HfkpzCWGDpsnFPAOI22SdQ==/lib/arm/libsuperplayer.so (VideoChannel::video_play()+258) (BuildId: fcf1af443c8cfbc511f044fbfb24f53015c0d2dd)
2022-06-21 15:38:00.264 27798-27798/? A/DEBUG: #02 pc 000db89b /data/app/com.jk.superplayer-HfkpzCWGDpsnFPAOI22SdQ==/lib/arm/libsuperplayer.so (task_video_play(void*)+14) (BuildId: fcf1af443c8cfbc511f044fbfb24f53015c0d2dd)
2022-06-21 15:38:00.265 27798-27798/? A/DEBUG: #03 pc 000ab98b /apex/com.android.runtime/lib/bionic/libc.so (__pthread_start(void*)+20) (BuildId: 7103c0ea4dad751f797aed4598de945f)
2022-06-21 15:38:00.265 27798-27798/? A/DEBUG: #04 pc 000629b3 /apex/com.android.runtime/lib/bionic/libc.so (__start_thread+30) (BuildId: 7103c0ea4dad751f797aed4598de945f)
addr2line
addr2line命令来自于英文词组”address to line“的缩写,其功能是将函数地址解析成文件名或行号的工具。给出一个可执行文件中的地址或一个可重定位对象中的偏移部分的地址,使用调试信息来找出与之相关的文件名和行号。
语法格式
addr2line [参数] [地址]
常用参数:
参数 | 作用 |
---|---|
-a | 在函数名、文件和行号信息之前,显示地址,以十六进制形式 |
-b | 指定目标文件的格式为bfdname |
-e | 指定需要转换地址的可执行文件名 |
-j | 给出的地址代表指定section偏移,而非绝对地址 |
-C | 将低级别的符号名解码为用户级别的名字 |
-f | 在显示文件名、行号的同时显示函数名信息 |
-p | 每一个地址的信息占一行 |
addr2line使用步骤
第一步:
addr2line使用步骤在ndk目录中,根据设备abi找到对应目录,由于我的设备是arm架构就到arm-linux-androideabi-4.9文件夹下,比如:E:\Users\Aimee\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin,并在此目录下打开命令行窗口。
第二步:
查看报错日志确定发生crash的so,并找到其路径,可以到Android Studio编译的build目录中寻找,比如:build/intermediates/cmake/debug/obj/armeabi-v7a/
第三步:
接下来就是日志分析,可以看backtrace,下面有crash时的调用栈信息
#01 pc 000db9a7 /data/app/com.jk.superplayer-HfkpzCWGDpsnFPAOI22SdQ==/lib/arm/libsuperplayer.so (VideoChannel::video_play()+258) (BuildId: fcf1af443c8cfbc511f044fbfb24f53015c0d2dd)
可以看出是VideoChannel类的video_play方法报错的,但具体是哪一行报错就不知道了,这时我用就可以找到偏移地址(000db9a7)通过addr2line定位到具体行号,在命令行输入以下命令:
$ ./arm-linux-androideabi-addr2line.exe -f -C -e /f/as_project/SuperPlayer/app/build/intermediates/cmake/debug/obj/armeabi-v7a/libsuperplayer.so 000db9a7
命令输出结果如下:
定位错误
根据以上命令确定了错误在VideoChannel.cpp的111行,分析代码找到问题,原来是因为调用的函数指针没有初始化。解决native问题报错太麻烦了,不像java代码出错打印的日志可以直接定位到错误。