Android应用C/C++代码偶发SIGSEGV崩溃问题排查求助
Android C/C++应用SIGSEGV崩溃排查:定位无效内存地址
我有一个包含庞大C/C++代码库的Android应用,该应用偶尔会发生崩溃,崩溃日志如下:
05-17 20:16:10.407 7218 30969 F libc : Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x72745324 in tid 30969 (media), pid 7218 05-17 20:16:10.568 4069 4069 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 05-17 20:16:10.569 4069 4069 F DEBUG : Build fingerprint: samsung/starltexx/starlte:10/QP1A.190711.020/G960FXXUHFVG4:user/release-keys 05-17 20:16:10.569 4069 4069 F DEBUG : Revision: '26' 05-17 20:16:10.569 4069 4069 F DEBUG : ABI: 'arm' 05-17 20:16:10.569 4069 4069 F DEBUG : Timestamp: 2023-05-17 20:16:10+0200 05-17 20:16:10.569 4069 4069 F DEBUG : pid: 7218, tid: 30969, name: media 05-17 20:16:10.569 4069 4069 F DEBUG : uid: 10419 05-17 20:16:10.570 4069 4069 F DEBUG : signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x72745324 05-17 20:16:10.570 4069 4069 F DEBUG : r0 bfc3002c r1 72745320 r2 00000000 r3 d7a13e0f 05-17 20:16:10.570 4069 4069 F DEBUG : r4 000000de r5 b4ebeb28 r6 0000003c r7 c0caf850 05-17 20:16:10.570 4069 4069 F DEBUG : r8 b5305e70 r9 c1d87018 r10 c0cafa60 r11 ee0c7260 05-17 20:16:10.570 4069 4069 F DEBUG : ip bdc5b0b0 sp c0caf6d8 lr baa02675 pc bb26745a 05-17 20:16:10.616 4069 4069 F DEBUG : 05-17 20:16:10.616 4069 4069 F DEBUG : backtrace: 05-17 20:16:10.617 4069 4069 F DEBUG : #00 pc 0345045a (QueueBuffer::duration() const+550) 05-17 20:16:10.617 4069 4069 F DEBUG : #01 pc 03450029 (getRecvBuffer(unsigned int, void*, unsigned int, unsigned int*, pjmedia_frame*)+108) 05-17 20:16:10.617 4069 4069 F DEBUG : #02 pc 0344d3e9
查看调用回溯未发现崩溃的明确原因,我想知道是否有办法确定地址0xeed8fce0对应的位置,显然该地址已不在应用的地址空间映射中,或者至少应用被拒绝访问该地址。
定位无效内存地址的实用方法
1. 用addr2line解析符号
- 必须使用编译时生成的带调试符号的.so库(release包默认剥离符号,需保留编译产出的未剥离版本)
- 找到NDK对应ARM架构的addr2line工具,路径示例:
$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line - 执行解析命令:
参数说明:arm-linux-androideabi-addr2line -f -C -e lib你的库名.so 0xeed8fce0-f显示函数名,-C还原C++ mangled命名,-e指定目标库文件。
2. 检查进程内存映射
如果设备有root权限,可抓取崩溃进程的内存映射表,确认地址归属:
- 执行命令:
adb shell cat /proc/7218/maps > mem_maps.txt - 打开
mem_maps.txt,搜索0xeed8fce0,查看该地址是否落在某个加载模块的区间内,或是完全无效的内存区域。
3. GDB调试直接查询
- 推送GDBserver到设备并附加进程:
adb push $NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/gdbserver /data/local/tmp/ adb shell chmod +x /data/local/tmp/gdbserver adb shell /data/local/tmp/gdbserver :1234 --attach 7218 - 本地用NDK的GDB连接并查询符号:
该命令会直接返回地址对应的函数或变量信息。$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gdb (gdb) target remote :1234 (gdb) info symbol 0xeed8fce0
额外提示
- 日志中的
SEGV_ACCERR说明是无权限访问内存,大概率是野指针、已释放内存重复访问、数组越界等问题导致。 - 崩溃触发点在
QueueBuffer::duration(),可重点检查该函数内的指针操作,比如是否访问了未初始化或已销毁的QueueBuffer对象。
内容的提问来源于stack exchange,提问作者René Heuven
相关产品推荐
相关产品推荐

