Android NDK 开发中的崩溃排查

Android NDK 开发中的崩溃排查

  • 解析崩溃的内存地址(比如 #00 pc 7a3b6c /data/app/.../lib/arm64/libapp.so)

ndk-stack 批量解析

  • ndk-stack 是 NDK 开发用来解析崩溃日志,需要结合未剥离的 .so 文件(确保编译时保留调试符号,避免 strip 剥离符号)中的调试符号,还原堆栈信息(比如 Windows 上的 \AndroidSdk\ndk\27.0.12077973\ndk-stack.cmd 文件)

  • 能够自动匹配 .so 调试符号,批量解析日志中的所有堆栈帧,直接输出文件名、行号和函数名(自动将崩溃 pc 地址映射到源代码的行号和方法名)

  • 1 保存日志到文件后进行解析

  • 最终文件内容必须包含 *** *** *** *** *** 开头那一行才能解析

shell 复制代码
# 将带崩溃日志的 logcat 内容捕获输出(Ctrl+C 停止)
adb logcat > D:/temp/arm64-v8a/crash.log
# 也可以按需捕获筛选出 NDK-StackTrace:E (只保留标签为 NDK-StackTrace 的 Error 级日志,对应代码中 LOGE 输出)的日志
adb logcat -s NDK-StackTrace:E > crash_log.txt

# 可以先确认设备 ABI,以保证选择正确的 .so 文件
adb shell cat /proc/cpuinfo
adb shell getprop ro.product.cpu.abi
adb shell getprop ro.product.cpu.abilist
shell 复制代码
# ndk-stack 存放在 \AndroidSdk\ndk\27.0.12077973 目录下
# -sym 参数(--symbols)指定包含符号表(调试信息)的 .so 文件(或 .debug 文件)的父目录(工具会自动递归查找目录下所有文件,比如 Debug 模式的 .so 或 Release 模式的 .so.debug)
# -dump 指定崩溃日志文件路径
ndk-stack -sym D:/temp/arm64-v8a -dump D:/temp/arm64-v8a/crash.log
shell 复制代码
# 也可以直接将结果输出到指定文件
ndk-stack -sym D:/temp/arm64-v8a -dump D:/temp/arm64-v8a/crash.log > D:/temp/arm64-v8a/crash_dump.log
  • 2 通过 adb logcat 实时输出日志
shell 复制代码
adb logcat | ndk-stack -sym $PROJECT_PATH/app/build/intermediates/cmake/debug/obj/arm64-v8a
adb logcat | ndk-stack -sym $PROJECT_PATH/app/build/intermediates/cxx/debug/obj/arm64-v8a
adb logcat | ndk-stack -sym $PROJECT_PATH/app/build/intermediates/cxx/debug/<hash>/obj/arm64-v8a

addr2line 单个地址解析

  • addr2line 是 NDK 工具链中的底层工具,用于解析单个堆栈地址对应的文件名、行号和函数名,适合快速验证单个地址
  • 新版本的 NDK 统一名为 llvm-addr2line,不再区分架构前缀,所有架构使用同一个命令(比如 Windows 上的 \AndroidSdk\ndk\27.0.12077973\toolchains\llvm\prebuilt\windows-x86_64\bin>llvm-addr2line.exe 文件,旧版本的 NDK 必须使用与 .so 架构一致的工具进行操作)
shell 复制代码
# 00000000011cc48c 是单个堆栈地址
# -e 参数(--exe)指定符号表 .so 文件
llvm-addr2line -e D:/temp/arm64-v8a/libpwrtcsdkandroid.so 00000000011cc48c
# 打印出对应的文件名、行号
/home/ubuntu/rtc-build/paho.mqtt.cpp/include/mqtt/message.h:251
shell 复制代码
# -f 参数(--functions)显示函数名
llvm-addr2line -e D:/temp/arm64-v8a/libpwrtcsdkandroid.so -f 00000000011cc48c
_ZNK4mqtt7message9get_topicEv
/home/ubuntu/rtc-build/paho.mqtt.cpp/include/mqtt/message.h:251
shell 复制代码
# -C 参数(--demangle)解码 C++ 符号(Demangle),就是还原 C++ 符号
llvm-addr2line -e D:/temp/arm64-v8a/libpwrtcsdkandroid.so -f -C 00000000011cc48c
mqtt::message::get_topic() const
/home/ubuntu/rtc-build/paho.mqtt.cpp/include/mqtt/message.h:251
相关推荐
遥不可及zzz1 小时前
Android 接入UMP
android
Coder_Boy_3 小时前
基于SpringAI的在线考试系统设计总案-知识点管理模块详细设计
android·java·javascript
冬奇Lab3 小时前
【Kotlin系列03】控制流与函数:从if表达式到Lambda的进化之路
android·kotlin·编程语言
冬奇Lab3 小时前
稳定性性能系列之十二——Android渲染性能深度优化:SurfaceFlinger与GPU
android·性能优化·debug
冬奇Lab5 小时前
稳定性性能系列之十一——Android内存优化与OOM问题深度解决
android·性能优化
用户74589002079546 小时前
线程池
android
专注前端30年6 小时前
【PHP开发与安全防护实战】性能调优手册
android·安全·php
王正南7 小时前
安卓逆向之LSposed开发(一)
android·xposed·lsposed
YIN_尹8 小时前
【MySQL】数据类型(上)
android·mysql·adb