Cocos2dx-如何利用NDK分析崩溃日志

本文转载于:http://www.cnblogs.com/jhzhu/p/3801640.html

背景介绍

  1. 本文主要内容: 利用android的crash log来对c++开发的android应用进行错误定位.
  2. 容易稳定复现的BUG, 一般可以通过断点调试来解决. 如果测试人员也无法稳定复现, log就成了程序吊定位问题的救命稻草.
  3. 通用操作系统都有自己的日志系统, android也不例外. 救命稻草已经给你了~ ( 怎样查看android的系统日志 )
  4. 但是, android的系统日志在c++代码崩溃时, 打印的都是内存地址和寄存器. 比如, 这样:
06-20 15:54:35.331 23889 23889 I DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
06-20 15:54:35.331 23889 23889 I DEBUG   : Build fingerprint: ‘google/razorg/deb:4.4.2/KOT49H/937116:user/release-keys‘
06-20 15:54:35.331 23889 23889 I DEBUG   : Revision: ‘0‘
06-20 15:54:35.331 23889 23889 I DEBUG   : pid: 1981, tid: 2020, name: Thread-3399  >>> com.guangyou.ddgame <<<
06-20 15:54:35.331 23889 23889 I DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000028
06-20 15:54:35.431   187   710 D audio_hw_primary: out_set_parameters: enter: usecase(0: deep-buffer-playback) kvpairs: routing=2
06-20 15:54:35.511 23889 23889 I DEBUG   :     r0 76d94458  r1 00000000  r2 00000000  r3 00000000
06-20 15:54:35.511 23889 23889 I DEBUG   :     r4 760c1a48  r5 751e2440  r6 00000001  r7 760c1a48
06-20 15:54:35.511 23889 23889 I DEBUG   :     r8 00000001  r9 76c96f3c  sl 76c861c0  fp 76d94444
06-20 15:54:35.511 23889 23889 I DEBUG   :     ip 00000001  sp 76d94430  lr 75a81bd8  pc 75a81bdc  cpsr 600f0010
06-20 15:54:35.511 23889 23889 I DEBUG   :     d0  746968775f327865  d1  6a6e6169642f675f
06-20 15:54:35.511 23889 23889 I DEBUG   :     d2  5f6f616978757169  d3  676e702e6e776f6d
06-20 15:54:35.511 23889 23889 I DEBUG   :     d4  0000000009000000  d5  0000000000000000
06-20 15:54:35.511 23889 23889 I DEBUG   :     d6  0000000000000000  d7  0000000000000000

这密密麻麻的都是些神马, 是人看的么?

饿. 这个麻… 谁让你当程序猿! 让你当! 活该要看天书!

硬着头皮也要来, 我们就来讲讲怎么消化天书吧~

怎样获取android的系统日志

假设你已经安装了 Android Develop Tools, 可以成功调用adb. 并打开android开发用机的调试模式, 连接到电脑.

打开命令行, 在命令行输入: adb logcat. 就可以看到满屏幕的日志啦.  
输入adb logcat --help可以看到 logcat的用法提示.

这里有两个参数特别提醒一下, 比较常用: 
1. -v XXXX: 用来选择log输出样式, 一般建议 threadtime, 更加详细. 
2. -d: 让log一次性输出后马上完毕. 如果没有此命令, logcat 工具会一直输出, 即使更新在界面上.

如果需要保存log到文件, 方便以后查看. 可输入命令: 
adb logcat -v threadtime -d > log.txt

理解NDK的crash log

如果你用c++开发的android应用在运行过程中, c++代码发生错误导致程序崩溃, 系统就会记录 crash log到上述的系统日志中.

下面是我正在开发的游戏一次崩溃后, 截取的日志( 插个广告, 全名斗地主下载地址: http://sj.ddwan.com )

06-20 15:54:35.331 23889 23889 I DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
06-20 15:54:35.331 23889 23889 I DEBUG   : Build fingerprint: ‘google/razorg/deb:4.4.2/KOT49H/937116:user/release-keys‘
06-20 15:54:35.331 23889 23889 I DEBUG   : Revision: ‘0‘
06-20 15:54:35.331 23889 23889 I DEBUG   : pid: 1981, tid: 2020, name: Thread-3399  >>> com.guangyou.ddgame <<<
06-20 15:54:35.331 23889 23889 I DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000028
06-20 15:54:35.431   187   710 D audio_hw_primary: out_set_parameters: enter: usecase(0: deep-buffer-playback) kvpairs: routing=2
06-20 15:54:35.511 23889 23889 I DEBUG   :     r0 76d94458  r1 00000000  r2 00000000  r3 00000000
06-20 15:54:35.511 23889 23889 I DEBUG   :     r4 760c1a48  r5 751e2440  r6 00000001  r7 760c1a48
06-20 15:54:35.511 23889 23889 I DEBUG   :     r8 00000001  r9 76c96f3c  sl 76c861c0  fp 76d94444
06-20 15:54:35.511 23889 23889 I DEBUG   :     ip 00000001  sp 76d94430  lr 75a81bd8  pc 75a81bdc  cpsr 600f0010
06-20 15:54:35.511 23889 23889 I DEBUG   :     d0  746968775f327865  d1  6a6e6169642f675f
06-20 15:54:35.511 23889 23889 I DEBUG   :     d2  5f6f616978757169  d3  676e702e6e776f6d
06-20 15:54:35.511 23889 23889 I DEBUG   :     d4  0000000009000000  d5  0000000000000000
06-20 15:54:35.511 23889 23889 I DEBUG   :     d6  0000000000000000  d7  0000000000000000
06-20 15:54:35.511 23889 23889 I DEBUG   :     d8  0000000000000000  d9  0000000000000000
06-20 15:54:35.511 23889 23889 I DEBUG   :     d10 0000000000000000  d11 0000000000000000
06-20 15:54:35.511 23889 23889 I DEBUG   :     d12 0000000000000000  d13 0000000000000000
06-20 15:54:35.511 23889 23889 I DEBUG   :     d14 0000000000000000  d15 0000000000000000
06-20 15:54:35.511 23889 23889 I DEBUG   :     d16 c3c3c3c3c3c3c3c3  d17 c3c3c3c3c3c3c3c3
06-20 15:54:35.511 23889 23889 I DEBUG   :     d18 41c7ddc227000000  d19 3ff0000000000000
06-20 15:54:35.511 23889 23889 I DEBUG   :     d20 3f811110896efbb2  d21 3fd7096611460fdb06-2015:54:35.5112388923889 I DEBUG   :     d22 c0176a8ee0000000  d23 bfc5230c760b0605
06-2015:54:35.5112388923889 I DEBUG   :     d24 0000000000000000  d25 3fc7922925a107e206-2015:54:35.5112388923889 I DEBUG   :     d26 3fdaa0f8fab43e33  d27 3fb43ad076b251ab06-2015:54:35.5112388923889 I DEBUG   :     d28 3fa15cb6bdc3c156  d29 3ec6cd878c3b46a706-2015:54:35.5112388923889 I DEBUG   :     d30 3f65f3b6b9b97e01  d31 3ef99342e0ee506906-2015:54:35.5112388923889 I DEBUG   :     scr 2000001206-2015:54:35.5112388923889 I DEBUG   :06-2015:54:35.5112388923889 I DEBUG   : backtrace:06-2015:54:35.5112388923889 I DEBUG   :#00  pc 0089cbdc  /data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::Texture2D::getContentSize() const+32)06-2015:54:35.5112388923889 I DEBUG   :#01  pc 0088f8dc  /data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::Sprite::setTexture(std::string const&)+128)06-2015:54:35.5112388923889 I DEBUG   :#02  pc 007863dc  /data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::ui::Button::loadTextureDisabled(std::string const&, cocos2d::ui::Widget::TextureResType)+336)06-2015:54:35.5112388923889 I DEBUG   :06-2015:54:35.5112388923889 I DEBUG   : stack:06-2015:54:35.5112388923889 I DEBUG   :76d943f00000000106-2015:54:35.5112388923889 I DEBUG   :76d943f44006bc0d/system/lib/libc.so (free+12)06-2015:54:35.5112388923889 I DEBUG   :76d943f876a72c5406-2015:54:35.5112388923889 I DEBUG   :76d943fc75eca614/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so
06-2015:54:35.5112388923889 I DEBUG   :76d94400751c23c8[anon:libc_malloc]06-2015:54:35.5112388923889 I DEBUG   :76d94404751c23c8[anon:libc_malloc]06-2015:54:35.5112388923889 I DEBUG   :76d94408751c23c8[anon:libc_malloc]06-2015:54:35.5112388923889 I DEBUG   :76d9440c75a749b4/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::Sprite::setTexture(cocos2d::Texture2D*)+128)06-2015:54:35.5112388923889 I DEBUG   :76d944100000003d06-2015:54:35.5112388923889 I DEBUG   :76d9441400e8efc806-2015:54:35.5112388923889 I DEBUG   :76d944180000000006-2015:54:35.5112388923889 I DEBUG   :76d9441c0000000006-2015:54:35.5112388923889 I DEBUG   :76d944200000000006-2015:54:35.5112388923889 I DEBUG   :76d9442476d94458[stack:2020]06-2015:54:35.5112388923889 I DEBUG   :76d944280000002006-2015:54:35.5112388923889 I DEBUG   :76d9442c76d94444[stack:2020]06-2015:54:35.5112388923889 I DEBUG   :#00  76d94430  0000000006-2015:54:35.5112388923889 I DEBUG   :76d9443476d94458[stack:2020]06-2015:54:35.5112388923889 I DEBUG   :76d9443876a6618406-2015:54:35.5112388923889 I DEBUG   :76d9443c760c1a48/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so
06-2015:54:35.5112388923889 I DEBUG   :76d9444076d9447c[stack:2020]06-2015:54:35.5112388923889 I DEBUG   :76d9444475a748e0/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::Sprite::setTexture(std::stringconst&)+132)06-2015:54:35.5112388923889 I DEBUG   :#01  76d94448  76d944ec  [stack:2020]06-2015:54:35.5112388923889 I DEBUG   :76d9444c793ff0e8[anon:libc_malloc]06-2015:54:35.5112388923889 I DEBUG   :76d9445076a72c5406-2015:54:35.5112388923889 I DEBUG   :76d944540000000006-2015:54:35.5112388923889 I DEBUG   :76d944580000000006-2015:54:35.5112388923889 I DEBUG   :76d9445c0000000006-2015:54:35.5112388923889 I DEBUG   :76d944600000000006-2015:54:35.5112388923889 I DEBUG   :76d944640000000006-2015:54:35.5112388923889 I DEBUG   :76d944680000000006-2015:54:35.5112388923889 I DEBUG   :76d9446c0000000006-2015:54:35.5212388923889 I DEBUG   :76d944707b91dcf8[anon:libc_malloc]06-2015:54:35.5212388923889 I DEBUG   :76d9447478ce6c50[anon:libc_malloc]06-2015:54:35.5212388923889 I DEBUG   :76d9447876d944b4[stack:2020]06-2015:54:35.5212388923889 I DEBUG   :76d9447c7596b3e0/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::ui::Button::loadTextureDisabled(std::stringconst&, cocos2d::ui::Widget::TextureResType)+340)06-2015:54:35.5212388923889 I DEBUG   :#02  76d94480  0000000106-2015:54:35.5212388923889 I DEBUG   :76d944840000000006-2015:54:35.5212388923889 I DEBUG   :76d9448876d944ec[stack:2020]06-2015:54:35.5212388923889 I DEBUG   :76d9448c793fe780[anon:libc_malloc]06-2015:54:35.5212388923889 I DEBUG   :76d9449076d944f0[stack:2020]06-2015:54:35.5212388923889 I DEBUG   :76d94494793ff0e8[anon:libc_malloc]06-2015:54:35.5212388923889 I DEBUG   :76d944980000000106-2015:54:35.5212388923889 I DEBUG   :76d9449c4006bc0d/system/lib/libc.so (free+12)06-2015:54:35.5212388923889 I DEBUG   :76d944a076a72c5406-2015:54:35.5212388923889 I DEBUG   :76d944a475eca614/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so
06-2015:54:35.5212388923889 I DEBUG   :76d944a878ce6c50[anon:libc_malloc]06-2015:54:35.5212388923889 I DEBUG   :76d944ac78ce6c50[anon:libc_malloc]06-2015:54:35.5212388923889 I DEBUG   :76d944b076d9455c[stack:2020]06-2015:54:35.5212388923889 I DEBUG   :76d944b475924e54/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocostudio::ButtonReader::setPropsFromJsonDictionary(cocos2d::ui::Widget*, rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>>const&)+752)06-2015:54:35.5212388923889 I DEBUG   :76d944b80000000006-2015:54:35.5212388923889 I DEBUG   :76d944bc78ce6c50[anon:libc_malloc]06-2015:54:35.5212388923889 I DEBUG   :06-2015:54:35.5212388923889 I DEBUG   : memory near r0:06-2015:54:35.5212388923889 I DEBUG   :76d9443876a66184760c1a4876d9447c75a748e006-2015:54:35.5212388923889 I DEBUG   :76d9444876d944ec793ff0e876a72c5400000000...06-2015:54:35.5212388923889 I DEBUG   :06-2015:54:35.5212388923889 I DEBUG   : memory near r4:06-2015:54:35.5212388923889 I DEBUG   :760c1a28760811c875ee318c75ee319475ee319c06-2015:54:35.5212388923889 I DEBUG   :760c1a384006d09175f9a1f475f4ee5c75e8ea0c...

下面来逐行解读: 
1. ndk crash log以*** *** *** *** ***开始. 
2. 第一行Build fingerprint: ‘google/razorg/deb:4.4.2/KOT49H/937116:user/release-keys‘ 指明了运行的Android版本, 如果您有多份crash dump的话这个信息就比较有用了. 
3. 接着一行显示的是当前的线程id(pid)和进程id(tid). 如果当前崩溃的线程是主线程的话, pid和tid会是一样的~ 
4. 第四行, 显示的是unix信号. 这里的signal 11, 即SIGSEGV, 表示段错误, 是最常见的信号.(什么是unix信号什么是SIGSEGV
5. 接下来的部分是系统寄存器的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. 表示当前
运行环境和状态的一些字节位.

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

利用ndk-stack定位崩溃代码

上面的一些信息能简单的帮你定位以下问题. 如果信息量还不够大的话, 那就还有最后一招: 还原历史.

Android NDK自从版本R6开始, 提供了一个工具ndk-stack( 在目录{ndk_root}/中 ). 这个工具能自动分析dump下来的crash log, 将崩溃时的调用内存地址和c++代码一行一行对应起来.

我们先看一下用法, 执行命令ndk-stack --help

Usage:
   ndk-stack -sym <path> [-dump <path>]

      -sym  Contains full path to the root directory for symbols.
      -dump Contains full path to the file containing the crash dump.
            This is an optional parameter. If ommited, ndk-stack will
            read input data from stdin
  • -dump参数很容易理解, 即dump下来的log文本文件. ndk-stack会分析此文件.
  • -sym参数就是你android项目下,编译成功之后,obj目录下的文件.

下面我们就来示范一下:

$ adb logcat | ndk-stack -sym ./obj/local/armeabi
********** Crash dump: **********
Build fingerprint: ‘htc_wwe/htc_bravo/bravo:2.3.3/
GRI40/96875.1:user/release-keys‘
pid: 1723, tid: 1743  >>> com.packtpub.droidblaster <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0000000c
Stack frame #00  pc 00010a2c  /data/data/com.packtpub.droidblaster/lib/libdroidblaster.so: Routine update in /home/packt/Project/Chapter11/DroidBlaster_Part11/jni/TimeService.cpp:25
Stack frame #01  pc 00009fcc  /data/data/com.packtpub.droidblaster/lib/libdroidblaster.so: Routine onStep in /home/packt/Project/Chapter11/DroidBlaster_Part11/jni/DroidBlaster.cpp:53
Stack frame #02  pc 0000a348  /data/data/com.packtpub.droidblaster/lib/libdroidblaster.so: Routine run in /home/packt/Project/Chapter11/DroidBlaster_Part11/jni/EventLoop.cpp:49
Stack frame #03  pc 0000f994  /data/data/com.packtpub.droidblaster/lib/libdroidblaster.so: Routine android_main in /home/packt/Project/Chapter11/DroidBlaster_Part11/jni/Main.cpp:31
...

熟悉的代码出现啦~~

Written with StackEdit.

时间: 2024-10-11 21:06:43

Cocos2dx-如何利用NDK分析崩溃日志的相关文章

利用LogParser分析IIS日志

LogParser是微软官方出品的用于读取分析IIS日志的工具,使用类SQL语句过滤文本日志内容,并可将内容导出到csv.sqlserver作进一步分析 下载地址:http://www.microsoft.com/en-us/download/details.aspx?id=24659 目前最新版本为2.2,下载后一直下一步,默认安装目录为:C:\Program Files (x86)\Log Parser 2.2\     一.获取IIS日志 记日志时间默认是UTC,如要使用本地时间记录,可勾

烂泥:利用awstats分析nginx日志

昨天把nginx的日志进行了切割,关于如何切割nginx日志,可以查看<烂泥:切割nginx日志>这篇文章. 今天打算分析下nginx日志,要分析nginx日志,我们可以通过shell脚本和第三方软件awstats进行分析,在此我们选择的是通过第三方软件awstats进行分析. 要使用awstats分析nginx日志,我们要安装awstats,而在安装awstats之前,我们需要先来介绍下awstats是什么? 一.awstats是什么 awstats是一个免费非常简洁而且强大有个性的基于Pe

iOS应用崩溃日志分析

转自raywenderlich 作为一名应用开发者,你是否有过如下经历? 为确保你的应用正确无误,在将其提交到应用商店之前,你必定进行了大量的测试工作.它在你的设备上也运行得很好,但是,上了应用商店后,还是有用户抱怨会闪退 ! 如果你跟我一样是个完美主义者,你肯定想将应用做到尽善尽美.于是你打开代码准备修复闪退的问题……但是,从何处着手呢? 这时iOS崩溃日志派上用场了.在大多数情况下,你能从中了解到关于闪退的详尽.有用的信息. 通过本教程,你将学习到一些常见的崩溃日志案例,以及如何从开发设备和

iOS 应用崩溃日志分析

通过本教程,你将学习到一些常见的崩溃日志案例,以及如何从开发设备和iTunes Connect上获取崩溃日志文件.你还将学习到符号化( symbolication),从日志追踪到代码 .你还将学习调试一个在待定情况下会闪退的应用. 让我们开始动手吧! 什么是崩溃日志,从哪里能得它? iOS设备上的应用闪退时,操作系统会生成一个崩溃报告,也叫崩溃日志,保存在设备上. 崩溃日志上有很多有用的信息,包括应用是什么情况下闪退的.通常,上面有每个正在执行线程的完整堆栈跟踪信息,所以你能从中了解到闪退发生时

iOS应用崩溃日志分析-备用

作为一名应用开发者,你是否有过如下经历? 为确保你的应用正确无误,在将其提交到应用商店之前,你必定进行了大量的测试工作.它在你的设备上也运行得很好,但是,上了应用商店后,还是有用户抱怨会闪退 ! 如果你跟我一样是个完美主义者,你肯定想将应用做到尽善尽美.于是你打开代码准备修复闪退的问题……但是,从何处着手呢? 这时iOS崩溃日志派上用场了.在大多数情况下,你能从中了解到关于闪退的详尽.有用的信息. 通过本教程,你将学习到一些常见的崩溃日志案例,以及如何从开发设备和iTunes Connect上获

【转】iOS应用崩溃日志分析

作为一名应用开发者,你是否有过如下经历? 为确保你的应用正确无误,在将其提交到应用商店之前,你必定进行了大量的测试工作.它在你的设备上也运行得很好,但是,上了应用商店后,还是有用户抱怨会闪退 ! 如果你跟我一样是个完美主义者,你肯定想将应用做到尽善尽美.于是你打开代码准备修复闪退的问题……但是,从何处着手呢? 这时iOS崩溃日志派上用场了.在大多数情况下,你能从中了解到关于闪退的详尽.有用的信息. 通过本教程,你将学习到一些常见的崩溃日志案例,以及如何从开发设备和iTunes Connect上获

iOS应用崩溃日志分析 iOS应用崩溃日志揭秘

转自:http://www.raywenderlich.com/zh-hans/30818/ios%E5%BA%94%E7%94%A8%E5%B4%A9%E6%BA%83%E6%97%A5%E5%BF%97%E6%8F%AD%E7%A7%98 这篇文章还能够在这里找到 英语 Learn how to make sense of crash logs! 本文作者是 Soheil Moayedi Azarpour, 他是一名独立iOS开发人员. 作为一名应用开发人员,你是否有过例如以下经历? 为确保

如何通过友盟分析发布后App崩溃日志-b

要分析崩溃日志,首先需要保留发布时的编译出来的.xcarchive文件.这个文件包含了.DSYM文件. 我一般的做法是,发布成功后,把这个文件.xcarchive直接提交到代码版本库对应的版本分支里,这样就不会搞丢了. 这个文件在哪呢?打开XCode->菜单Window->Organizer,在编译成功的文件上右键,就能打开了. 两种比较麻烦的方法. 第一种方法: 使用dwarfdump命令 dwarfdump --uuid xx.app.dSYM     用来得到app的UUID.dwarf

i o s 崩溃日志分析

转自:http://blog.csdn.net/totogo2010/article/details/39892467 要分析崩溃日志,首先需要保留发布时的编译出来的.xcarchive文件.这个文件包含了.DSYM文件. 我一般的做法是,发布成功后,把这个文件.xcarchive直接提交到代码版本库对应的版本分支里,这样就不会搞丢了. 这个文件在哪呢?打开XCode->菜单Window->Organizer,在编译成功的文件上右键,就能打开了. 两种比较麻烦的方法. 第一种方法: 使用dwa