NDK native crash 问题分析

本文详细列举了编程中常见的错误类型,如初始化错误、数组索引越界等,并通过一个具体的NativeCrash案例,展示了如何使用命令进行错误定位和调试,包括利用addr2line和objdump等工具进行反汇编分析。

常见的错误类型如下:

    初始化错误
    访问错误

    数组索引访问越界
    指针对象访问越界
    访问空指针对象
    访问无效指针对象
    迭代器访问越界

    内存泄露
    参数错误
    堆栈溢出
    类型转换错误
    数字除0错误

 

常用命令:

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Native Crash TIME: 3875438
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: ':userdebug/test-keys'
Revision: '0'
ABI: 'arm'
pid: 319, tid: 20699, name: afctrl  >>> /vendor/bin/hw/android.hardware.camera.provider@2.4-service <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x280028
    r0  a6ec4b88  r1  a7c72540  r2  00280029  r3  a724123c
    r4  a76fa000  r5  a7c72e70  r6  a7c771f8  r7  a7c72540
    r8  a6ec5490  r9  a7c72c48  r10 a7c72e70  r11 a6ec5470
    ip  a7253f40  sp  a6ec4b30  lr  a72430e4  pc  00280028

backtrace:
    #00 pc 00280028  <unknown>
    #01 pc 000030e0  /vendor/lib/libspa.so (spa_calculation+92)
    #02 pc 0002d4df  /vendor/lib/libispalg.so (caf_monitor_calc+42)
    #03 pc 00029f9f  /vendor/lib/libispalg.so (sprd_afv1_process+1530)
    #04 pc 0002655b  /vendor/lib/libispalg.so (afctrl_ctrl_thr_proc+394)
    #05 pc 000022e7  /vendor/lib/libcamcommon.so (cmr_common_routine+114)
    #06 pc 00063a55  /system/lib/libc.so (__pthread_start(void*)+22)
    #07 pc 0001df55  /system/lib/libc.so (__start_thread+22)

 

直接定位行号:

toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-addr2line -e ~/armeabi-v7a/libspa.so 30e0

也可马反汇编出来具体看:
toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-objdump -d ~/armeabi-v7a/libspa.so --start-address=0x00001248 --stop-address=0x00003620

arm-linux-androideabi-objdump –S obj/local/armeabi/libhello-jni.so > hello.asm

以上两条命令都可以实现。

系统寄存器的dump信息.

  • rX( X=[0~9] ): 代表整数寄存器
  • dX( X=[0~31]): 是浮点指针寄存器
  • fp (or r11) : 指向当前正在执行的函数的堆栈底.
  • ip (or r12) : 一个寄存器, 我也没弄明白是干啥的.
  • sp (or r13) : 当前正在执行的函数的堆栈顶.(跟fp相对应)
  • lr (or r14) : link register . 简单来说, 当当前指令执行完了, 就会从这个寄存器获取地址, 来知道需要返回到哪里继续执行.
  • pc (or r15) : program counter. 存放下一条指令的地址.
  • cpsr : Current Program Status Register. 表示当前运行环境和状态的一些字节位.

    1. Crash dump还包含PC之前和之后的一些内存字段.
    2. 最后, 是崩溃时的调用堆栈. 如果你执行的是debug版本, 还能还原一些c++代码.

 

 

 

<think>好的,我现在需要帮助用户解决如何通过NDK生成的crash日志精确定位到对应的代码行数的问题。首先,我应该回顾一下用户提供的引用内容,看看有没有相关的信息可以利用。 用户提到了引用[2]中的内容,里面提到willCrash()方法出错在260行,这说明在crash日志中可能已经包含了具体的行号信息。但用户可能需要更详细的步骤来自己定位问题。另外,引用[3]提到定位问题需要复现步骤,而引用[4]涉及JNI方法声明和参数类型,可能和崩溃原因相关。 接下来,我需要整理NDK崩溃定位的常规方法。首先,NDK崩溃通常会生成堆栈跟踪,但如果没有符号化,这些信息是难以理解的。所以第一步应该是确保有符号表(比如.so文件附带调试信息)。然后,使用addr2line或者ndk-stack工具将地址转换为代码行数。 可能用户遇到的问题是如何使用这些工具。例如,使用ndk-stack需要将日志通过adb获取,然后运行命令进行解析。而addr2line则需要具体的地址和对应的带有调试信息的.so文件。另外,编译时需要开启调试信息,即编译选项中加入-g,否则可能无法获取行号信息。 还要考虑日志中的崩溃类型,比如空指针、内存越界等,这些可能在日志中有不同的表现。同时,需要检查JNI代码中的常见错误,比如引用管理不当、数组越界、类型不匹配等,如引用[4]中的参数类型是否正确。 另外,用户可能需要知道如何设置Android项目的调试选项,确保生成带调试符号的Native库。可能在CMake或Android.mk中配置,例如在CMakeLists.txt中添加“set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g”)。 还有,如果崩溃发生在JNI函数中,可能需要结合Java和Native的堆栈信息,查看是否有对应的JNI错误,比如使用CheckJNI来检测问题,这可能在开发阶段帮助捕获错误。 总结下来,步骤应该是: 1. 确保编译时生成调试符号。 2. 获取崩溃日志(logcat)。 3. 使用ndk-stack或addr2line解析日志中的地址。 4. 结合代码审查可能的错误点,如JNI引用、参数传递等。 需要检查用户是否遗漏了某些步骤,比如未保留带符号的so文件,或者没有正确使用工具解析。此外,可能还需要建议用户使用Android Studio的LLDB调试工具,或者配置Breakpad来捕获更详细的崩溃信息。 最后,根据用户提供的引用,尤其是引用[2]和[3],需要强调复现步骤和精确解析日志的重要性。可能还需要提醒用户注意日志中的寄存器信息和崩溃地址对应的具体的代码段。</think>### 如何通过NDK生成的crash日志定位代码行数? #### 1. **确保编译时包含调试符号** - 在编译Native代码时,需在`CMakeLists.txt`或`Android.mk`中添加调试符号生成选项。例如: ```cmake set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") # 添加-g参数保留调试信息 ``` - **验证符号文件**:生成的`.so`文件应包含调试信息(可通过`file libxxx.so`检查是否包含`with debug_info`)。 #### 2. **获取完整的崩溃日志** - 使用`adb logcat`捕获崩溃日志,并过滤相关进程: ```bash adb logcat | grep "xxx" # 替换为崩溃的关键词或进程名 ``` - 典型NDK崩溃日志示例: ``` signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 backtrace: #00 pc 00001234 /data/app/lib/arm64/libnative.so (function_name+0x1234) ``` #### 3. **使用`ndk-stack`工具解析地址** - 将日志保存为文件(如`crash.log`),运行以下命令: ```bash ndk-stack -sym /path/to/obj/local/armeabi-v7a/ -dump crash.log ``` - `-sym`参数指定包含符号文件的目录(对应ABI架构)。 - **输出示例**: ``` #00 pc 00001234 libnative.so (function_name+1234) (file.cpp:260) ``` 直接显示代码文件和行号(如`file.cpp:260`)[^2]。 #### 4. **手动使用`addr2line`转换地址** - 若未集成`ndk-stack`,可用`addr2line`工具: ```bash aarch64-linux-android-addr2line -e libnative.so 00001234 ``` - 需选择对应架构的`addr2line`(位于NDK的`toolchains`目录下,如`aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin`)[^1]。 #### 5. **结合代码审查常见JNI错误** - **空指针或内存越界**:检查JNI函数中的指针操作和数组边界。 - **引用管理问题**:未正确释放局部引用(`DeleteLocalRef`)或误用全局引用。 - **参数类型不匹配**:如Java的`long`对应JNI的`jlong`,避免类型强制转换错误(参考引用[4]中的参数对应关系)。 #### 6. **使用Android Studio的LLDB调试** - 在Android Studio中启用`Debug native code`,断点调试Native代码。 - 若崩溃可稳定复现,直接运行并触发崩溃,IDE会自动定位到代码行[^3]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值