Android ndk开发,出现内存溢出或别的问题需要调试时,如何快速定位到源码位置,可以使用addr2line 和 ndk-stack 两个工具。在程序
内容主要分为一下几个部分:

1.Library Symbols (共享库的符号)2.Analyze Tools (可用到的分析工具)3.CrashLog – Header 4.CrashLog – Backtrace(For most crashes)5.CrashLog – Registers6.CrashLog – Memory7.CrashLog – Stack8.Library Base Address (共享库在内存中基地址)

1.Library Symbols (共享库的符号)
ndk提供了一些工具可以供程序员直接获取到出错的文件,函数以及行数。 但是这部分工具都需要没有去符号的共享库(通常是放在main/obj/local/armeabi-v7a)。而main/libs/armeabi-v7a中的共享库是去掉了符号的,所以直接从设备上抓下来的lib是不能够通过工具来找到对应的符号(而且没有去symbol的库比去掉的空间占用会大许多)。所以如果想要分析一份native crash,那么unstripped lib几乎不可缺少,但是即使是strip过的库也同样会包含少量的symbol。

2.Analyze Tools
即常用的辅助工具
1、addr2line ((ANDROID_NDK)\toolchains\arm-linux-androideabi-4.7\prebuilt\windows\bin)  
 #通过backtrace一栏提供的地址查询对应的符号,可以定位到文件,函数,行数.  
Usage: addr2line –aCfe libs
(trace_address)

2、ndk-stack (android-ndk-r8d\ndk-stack)
#相当于执行多次addr2line, 可以直接针对一份crash log使用,会输出所有backtrace里地址对应的symbol
Usage: ndk-stack –sym (libdirectory)dump (crash_log_file)

3、 objdump (android-ndk-r8d\toolchains\arm-linux-androideabi-4.7\prebuilt\windows\bin)
#Dump the object file. 通过汇编代码定位错误的原因,大部分复杂的问题可以通过这种方式得到解决。
Usage: objdump -S (objfile)> (output_file)

贴上一份crash log ,app crash时,打开android device moniter 查看log 找到 如下log

06-15 14:23:38.335: I/DEBUG(631): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***06-15 14:23:38.335: I/DEBUG(631): Build fingerprint: 'Xiaomi/hermes/hermes:5.0.2/LRX22G/V7.3.2.0.LHMCNDD:user/release-keys'06-15 14:23:38.335: I/DEBUG(631): Revision: '0'06-15 14:23:38.335: I/DEBUG(631): ABI: 'arm'06-15 14:23:38.335: I/DEBUG(631): pid: 30939, tid: 612, name: Thread-221  >>> sdk.live.com.xysdk <<<06-15 14:23:38.335: I/DEBUG(631): signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------06-15 14:23:38.355: V/AudioTrackShared(268): mAvailToClient=1024 stepCount=1024 minimum=153606-15 14:23:38.359: I/DEBUG(631): Abort message: 'art/runtime/thread.cc:1115] No pending exception expected: android.media.MediaCodec$CodecException: Error 0x80001001'06-15 14:23:38.359: I/DEBUG(631):     r0 00000000  r1 00000264  r2 00000006  r3 0000000006-15 14:23:38.359: I/DEBUG(631):     r4 e0574dd8  r5 00000006  r6 00000000  r7 0000010c06-15 14:23:38.359: I/DEBUG(631):     r8 00000000  r9 ab3150b0  sl ab7909f8  fp 0000000106-15 14:23:38.359: I/DEBUG(631):     ip 00000264  sp e0574878  lr f71fa4df  pc f7220094  cpsr 6007001006-15 14:23:38.359: I/DEBUG(631): backtrace:06-15 14:23:38.359: I/DEBUG(631):     #00 pc 0003c094  /system/lib/libc.so (tgkill+12)06-15 14:23:38.359: I/DEBUG(631):     #01 pc 000164db  /system/lib/libc.so (pthread_kill+66)06-15 14:23:38.359: I/DEBUG(631):     #02 pc 000170a7  /system/lib/libc.so (raise+10)06-15 14:23:38.359: I/DEBUG(631):     #03 pc 00013997  /system/lib/libc.so (__libc_android_abort+34)06-15 14:23:38.360: I/DEBUG(631):     #04 pc 000120c8  /system/lib/libc.so (abort+4)06-15 14:23:38.360: I/DEBUG(631):     #05 pc 002179a9  /system/lib/libart.so (art::Runtime::Abort()+132)06-15 14:23:38.360: I/DEBUG(631):     #06 pc 000a6e0d  /system/lib/libart.so (art::LogMessage::~LogMessage()+1292)06-15 14:23:38.360: I/DEBUG(631):     #07 pc 0022883f  /system/lib/libart.so (art::Thread::AssertNoPendingException() const+350)06-15 14:23:38.360: I/DEBUG(631):     #08 pc 000d3093  /system/lib/libart.so (art::ClassLinker::FindClass(art::Thread*, char const*, art::Handle)+30)06-15 14:23:38.360: I/DEBUG(631):     #09 pc 000d502d  /system/lib/libart.so (art::ClassLinker::ResolveType(art::DexFile const&, unsigned short, art::Handle, art::Handle)+136)06-15 14:23:38.360: I/DEBUG(631):     #10 pc 00070ba5  /system/lib/libart.so (_ZN3art11ClassLinker11ResolveTypeEtPNS_6mirror9ArtMethodE.part.112+104)06-15 14:23:38.360: I/DEBUG(631):     #11 pc 0015f561  /system/lib/libart.so (art::MethodHelper::GetClassFromTypeIdx(unsigned short, bool)+104)06-15 14:23:38.360: I/DEBUG(631):     #12 pc 0007277f  /system/lib/libart.so (art::CheckMethodArguments(art::mirror::ArtMethod*, unsigned int*)+190)06-15 14:23:38.360: I/DEBUG(631):     #13 pc 00214d75  /system/lib/libart.so (art::InvokeVirtualOrInterfaceWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+408)06-15 14:23:38.360: I/DEBUG(631):     #14 pc 0019f8e7  /system/lib/libart.so (art::JNI::CallVoidMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list)+274)06-15 14:23:38.360: I/DEBUG(631):     #15 pc 000baedb  /system/lib/libart.so (art::CheckJNI::CallVoidMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list)+90)06-15 14:23:38.360: I/DEBUG(631):     #16 pc 000cd17c  /data/app/sdk.live.com.xysdk-1/lib/arm/libxiaoyao_live.so (_JNIEnv::CallVoidMethod(_jobject*, _jmethodID*, ...)+52)**06-15 14:23:38.360: I/DEBUG(631):     #17 pc 000d1a78**  /data/app/sdk.live.com.xysdk-1/lib/arm/libxiaoyao_live.so (JMediacodecDecoder::decoder(unsigned char*, int, unsigned int)+128)06-15 14:23:38.360: I/DEBUG(631):     #18 pc 000d0a38  /data/app/sdk.live.com.xysdk-1/lib/arm/libxiaoyao_live.so (MediaStreamReceiver::VideoDecoderFunc(void*)+124)06-15 14:23:38.360: I/DEBUG(631):     #19 pc 00015c5b  /system/lib/libc.so (__pthread_start(void*)+30)06-15 14:23:38.360: I/DEBUG(631):     #20 pc 00013ceb  /system/lib/libc.so (__start_thread+6)

3.Crash Log - Header
信息头,包含当前系统版本有关的信息,如果是做平台级的开发,这将有助于定位当前的系统的开发版本。

I/DEBUG(631): Build fingerprint: 'Xiaomi/hermes/hermes:5.0.2/LRX22G/V7.3.2.0.LHMCNDD:user/release-keys'06-15 14:23:38.335: I/DEBUG(631): Revision: '0'06-15 14:23:38.335: I/DEBUG(631): ABI: 'arm'06-15 14:23:38.335: I/DEBUG(631): pid: 30939, tid: 612, name: Thread-221  >>> sdk.live.com.xysdk <<<

4.CrashLog – Backtrace(For most crashes)
看上面log

06-15 14:23:38.359: I/DEBUG(631): backtrace:06-15 14:23:38.359: I/DEBUG(631):     #00 pc 0003c094  /system/lib/libc.so (tgkill+12)06-15 14:23:38.359: I/DEBUG(631):     #01 pc 000164db  /system/lib/libc.so (pthread_kill+66)06-15 14:23:38.359: I/DEBUG(631):     #02 pc 000170a7  /system/lib/libc.so (raise+10)06-15 14:23:38.359: I/DEBUG(631):     #03 pc 00013997  /system/lib/libc.so (__libc_android_abort+34)

从上面这份backtrace可以看到包含一个pc地址和后面的symbol。部分错误可以通过只看这里的symbol发现问题所在。而如果想要更准确的定位,则需要借助ndk工具。 查看 pc d1a78

$  ~/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line -aCfe obj/local/armeabi-v7a/libxiaoyao_live.so d1a780x000d1a78如下是输出结果:定位到源码的位置JMediacodecDecoder::decoder(unsigned char*, int, unsigned int)/Users/apple/ycWorkSpace/workspace/kakaPushTemp/XYsdk/app/src/main/jni/src/android/mediacodec/JMediacodecDecoder.cpp:191

ndk-stack:

~/Library/Android/sdk/ndk-bundle/ndk-stack -sym obj/local/armeabi-v7a/libxiaoyao_live.so -dump ~/log.txt 

其分析结果如下:

********** Crash dump: **********Build fingerprint: 'Xiaomi/hermes/hermes:5.0.2/LRX22G/V7.3.2.0.LHMCNDD:user/release-keys'pid: 30939, tid: 612, name: Thread-221  >>> sdk.live.com.xysdk <<6 (SIGABRT), code -6 (SI_TKILL), fault addr --------Stack frame #00 pc 0003c094  /system/lib/libc.so (tgkill+12)Stack frame #01 pc 000164db  /system/lib/libc.so (pthread_kill+66)Stack frame #02 pc 000170a7  /system/lib/libc.so (raise+10)Stack frame #03 pc 00013997  /system/lib/libc.so (__libc_android_abort+34)Stack frame #04 pc 000120c8  /system/lib/libc.so (abort+4)Stack frame #05 pc 002179a9  /system/lib/libart.so (art::Runtime::Abort()+132)Stack frame #06 pc 000a6e0d  /system/lib/libart.so (art::LogMessage::~LogMessage()+1292)Stack frame #07 pc 0022883f  /system/lib/libart.so (art::Thread::AssertNoPendingException() const+350)Stack frame #08 pc 000d3093  /system/lib/libart.so (art::ClassLinker::FindClass(art::Thread*, char const*, art::Handle)+30)Stack frame #09 pc 000d502d  /system/lib/libart.so (art::ClassLinker::ResolveType(art::DexFile const&, unsigned short, art::Handle, art::Handle)+136)Stack frame #10 pc 00070ba5  /system/lib/libart.so (_ZN3art11ClassLinker11ResolveTypeEtPNS_6mirror9ArtMethodE.part.112+104)Stack frame #11 pc 0015f561  /system/lib/libart.so (art::MethodHelper::GetClassFromTypeIdx(unsigned short, bool)+104)Stack frame #12 pc 0007277f  /system/lib/libart.so (art::CheckMethodArguments(art::mirror::ArtMethod*, unsigned int*)+190)Stack frame #13 pc 00214d75  /system/lib/libart.so (art::InvokeVirtualOrInterfaceWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+408)Stack frame #14 pc 0019f8e7  /system/lib/libart.so (art::JNI::CallVoidMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list)+274)Stack frame #15 pc 000baedb  /system/lib/libart.so (art::CheckJNI::CallVoidMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list)+90)Stack frame #16 pc 000cd17c  /data/app/sdk.live.com.xysdk-1/lib/arm/libxiaoyao_live.so (_JNIEnv::CallVoidMethod(_jobject*, _jmethodID*, ...)+52): Routine _JNIEnv::CallVoidMethod(_jobject*, _jmethodID*, ...) at /Users/apple/Library/Android/sdk/ndk-bundle/platforms/android-17/arch-arm/usr/include/jni.h:650Stack frame #17 pc 000d1a78  /data/app/sdk.live.com.xysdk-1/lib/arm/libxiaoyao_live.so (JMediacodecDecoder::decoder(unsigned char*, int, unsigned int)+128): Routine JMediacodecDecoder::decoder(unsigned char*, int, unsigned int) at /Users/apple/ycWorkSpace/workspace/kakaPushTemp/XYsdk/app/src/main/jni/src/android/mediacodec/JMediacodecDecoder.cpp:191Stack frame #18 pc 000d0a38  /data/app/sdk.live.com.xysdk-1/lib/arm/libxiaoyao_live.so (MediaStreamReceiver::VideoDecoderFunc(void*)+124): Routine MediaStreamReceiver::VideoDecoderFunc(void*) at /Users/apple/ycWorkSpace/workspace/kakaPushTemp/XYsdk/app/src/main/jni/src/android/look/networkStreamReceiver/MediaStreamReceiver.cpp:230Stack frame #19 pc 00015c5b  /system/lib/libc.so (__pthread_start(void*)+30)Stack frame #20 pc 00013ceb  /system/lib/libc.so (__start_thread+6)

5.CrashLog – Registers
寄存器信息,可以通过这部分信息基本确定系统为什么会错。

06-15 14:23:38.359: I/DEBUG(631):     r0 00000000  r1 00000264  r2 00000006  r3 0000000006-15 14:23:38.359: I/DEBUG(631):     r4 e0574dd8  r5 00000006  r6 00000000  r7 0000010c06-15 14:23:38.359: I/DEBUG(631):     r8 00000000  r9 ab3150b0  sl ab7909f8  fp 0000000106-15 14:23:38.359: I/DEBUG(631):     ip 00000264  sp e0574878  lr f71fa4df  pc f7220094  cpsr 60070010

这部分信息展示了出错时的运行状态, 当前中断原因是收到SIGSEGV(通常crash也都是因为收到这个信号,也有少数是因为SIGFPE,即除0操作)。错误码是SEGV_MAPERR,常见的段错误。

 ~/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-objdump -S obj/local/armeabi-v7a/objs/xiaoyao_live/android/mediacodec/JMediacodecDecoder.o > ~/demo

反汇编,把.o 文件反编译为.s 文件
基本上配合log 及 addr2line 工具就可以定位到问题位置。

更多相关文章

  1. 使用android中的aapt查看安卓apk包信息
  2. :45套精美的 ( Android, iPhone, iPad ) 手机界面设计素材和线框
  3. Android开发必备的免费资源和工具
  4. Android中获取系统上安装的APP信息
  5. Android SDK: sdkmanager 命令行工具的使用(查看、安装、更新、卸
  6. android 手机信息获得
  7. Android 系统信息获取(CPU,RAM,ROM,Battery,SD-card,版本等)
  8. Android屏幕信息获取
  9. Android Studio有关详细信息, 请使用 -Xlint:deprecation 重新编

随机推荐

  1. android wifi adb调试
  2. Android 实际项目架构提炼开篇一
  3. android中的强指针和弱指针
  4. Android 与 H5 之间的互调
  5. 详解Android增量更新
  6. 一篇文章教你读懂UI绘制流程
  7. Looper,Handler,Message
  8. Google董事长:望Android遍布世界 智能机明
  9. Android目录结构(详解)
  10. 五步学会Android的ListView控件