Cocos2dx-如何利用NDK分析崩溃日志
2015-07-23 14:48
190 查看
本文转载于:/article/5810655.html
背景介绍
本文主要内容: 利用android的crash log来对c++开发的android应用进行错误定位.容易稳定复现的BUG, 一般可以通过断点调试来解决. 如果测试人员也无法稳定复现, log就成了程序吊定位问题的救命稻草.
通用操作系统都有自己的日志系统, android也不例外. 救命稻草已经给你了~ ( 怎样查看android的系统日志 )
但是, 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. 表示当前 运行环境和状态的一些字节位. |
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 ...
熟悉的代码出现啦~~
相关文章推荐
- Cocos2dx-本地消息推送
- cocos2d-x 3.0游戏实例学习笔记 《跑酷》第一步--- 开始界面
- Cocos2dx-角色创建与动画实现
- cocos2dX 音乐和声音效果
- Cocos2dx-自定义怪物伤害值
- Cocos2dx-背景无限循环播放
- Cocos2dx-Android混编实现头像切换(JNI使用)
- Cocos2dx-Android屏幕适配方案
- Cocos2dx-Mac下的环境配置
- Cocos2dx-C++和Lua数据通讯
- quick-cocos2dx lua中读取 加密 csv表
- Cocos-2d 坐标系及其坐标转换
- Cocos2dx-Lua与C++混合使用
- 在cocos2d-js-v3.0 中使用cocostudio UI的正确方式
- 如何使用cocos2dx-jsbinding 来处理分辨率适配
- Cocos2d-js的屏幕适配方案
- Cocos移植到Android-使用Eclipse交叉编译打包
- [Cocos2d-x v3.x官方文档]Cocos2d-x 3.0坐标系详解
- Cocos2d-JS坐标系
- cocos2dx坐标系统学习