使用cocos2dx android打包移植 android平台,怎么收集崩溃日志

作者简介:贾志凯,Testin崩溃分析()项目研发工程师,负责客户端SDK相关技术研发工作。5年移动互联网开发经验,曾任职于中科院、Symantec、Opera,对移动App的测试、分析有较深入的研究。
Android系统碎片化造成应用程序崩溃严重,在模拟器上运行良好的程序安装到某款手机上说不定就会出现崩溃的现象。而且,往往都是程序发布之后在用户端出现了崩溃现象。所以,如何及时捕获并收集Android平台的崩溃就显得愈发重要。目前,市面上已经有第三方SDK可以帮助开发者完成这一功能,本文将跟大家分享一下这些崩溃分析SDK的实现原理。
常见的Android崩溃有两类,一类是Java Exception异常,一类是Native Signal异常。我们将围绕这两类异常进行。对于很多基于Unity、Cocos平台的游戏,还会有C#、JavaScript、Lua等的异常,这里不做讨论。
Java代码的崩溃机制及实现
Android应用程序的开发是基于Java语言的,所以首先来分析第一类Android崩溃Java Exception。
Exception的分类及捕获
Java的异常可以分为两类:Checked Exception和UnChecked Exception。所有RuntimeException类及其子类的实例被称为Runt ime异常,即UnChecked Exception,不是RuntimeException类及其子类的异常实例则被称为Checked Exception。
Checked异常又称为编译时异常,即在编译阶段被处理的异常。编译器会强制程序处理所有的Checked异常,也就是用try…catch显式的捕获并处理,因为Java认为这类异常都是可以被处理(修复)的。在Java API文档中,方法说明时,都会添加是否throw某个exception,这个exception就是Checked异常。如果没有try…catch这个异常,则编译出错,错误提示类似于“Unhandled&
exception type xxxxx”。
该类异常捕获的流程是:
Checked异常一般是不引起Android App Crash的,注意是“一般”,这里之所以介绍,有两个原因:
UnChecked异常又称为运行时异常,即Runtime-Exception,最常见的莫过于NullPointerException。UnChecked异常发生时,由于没有相应的try…catch处理该异常对象,所以Java运行环境将会终止,程序将退出,也就是我们所说的Crash。当然,你可能会说,那我们把这些异常也try…catch住不就行了。理论上确实是可以的,但有两点会导致这种方案不可行:
没有try…catch住的异常,即Uncaught异常,都会导致应用程序崩溃。那么面对崩溃,我们是否可以做些什么呢?比如程序退出前,弹出个性化对话框,而不是默认的强制关闭对话框,或者弹出一个提示框安慰一下用户,甚至重启应用程序等。
其实Java提供了一个接口给我们,可以完成这些,这就是UncaughtExceptionHandler,该接口含有一个纯虚函数:public abstract void uncaughtException (Thread thread, Throwableex)。
Uncaught异常发生时会终止线程,此时,系统便会通知UncaughtExceptionHandler,告诉它被终止的线程以及对应的异常,然后便会调用uncaughtException函数。如果该handler没有被显式设置,则会调用对应线程组的默认handler。如果我们要捕获该异常,必须实现我们自己的handler,并通过以下函数进行设置:
public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler handler)
实现自定义的handler,只需要继承UncaughtExceptionHandler该接口,并实现uncaughtException方法即可。
static class MyCrashHandler implements UncaughtExceptionHandler{ @Override public void uncaughtException(Thread thread, final Throwable throwable) { // Deal this exception }
在任何线程中,都可以通过setDefaultUncaughtExceptionHandler来设置handler,但在Android应用程序中,全局的Application和Activity、Service都同属于UI主线程,线程名称默认为“main”。所以,在Application中应该为UI主线程添加UncaughtExceptionHandler,这样整个程序中的Activity、Service中出现的UncaughtException事件都可以被处理。
如果多次调用setDefaultUncaughtExceptionHandler设置handler,以最后一次为准。这也就是为什么多个抓崩溃的SDK同时使用,总会有一些SDK工作不正常。某些情况下,用户会既想利用第三方SDK收集崩溃,又想根据崩溃类型做出业务相关的处理。此时有两种方案:
static class MyCrashHandler implements UncaughtExceptionHandler { private UncaughtExceptionHandler originalH private MyCrashHandler(Context context) {
originalHandler = Thread.getDefaultUncaughtExceptionHandler();
@Override public void uncaughtException(Thread thread, final Throwable throwable) { // Deal this exception if (originalHandler != null) {
originalHandler.uncaughtException(thread, throwable);
获取Exception崩溃堆栈
捕获Exception之后,我们还需要知道崩溃堆栈的信息,这样有助于我们分析崩溃的原因,查找代码的Bug。异常对象的printStackTrace方法用于打印异常的堆栈信息,根据printStackTrace方法的输出结果,我们可以找到异常的源头,并跟踪到异常一路触发的过程。
public static String getStackTraceInfo(final Throwable throwable) {
String trace = &&; try {
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
throwable.printStackTrace(pw);
trace = writer.toString();
pw.close();
} catch (Exception e) { return &&;
Native代码的崩溃机制及实现
Android平台除了使用Java语言开发以外,还提供了对C/C++的支持。对于一些高CPU消耗的应用程序,Java语言很难满足对性能的要求,这时就需要使用C/C++进行开发,比如游戏引擎、信号处理等。但是Native代码只能开发动态链接库(so),然后Java通过JNI来调用so库。
Native崩溃分析与捕获
C++也可以通过try…catch去处理一些异常,但如果出现了Uncaught异常,so库就会引起崩溃。此时肯定无法通过Java的Uncaught-ExceptionHandler来处理,那么我们应该如何捕获Native代码的崩溃呢?熟悉Linux开发的人都知道,so库一般通过gcc/g++编译,崩溃时会产生信号异常。Android底层是Linux系统,所以so库崩溃时也会产生信号异常。那么如果我们能够捕获信号异常,就相当于捕获了Android Native崩溃。
信号其实是一种软件层面的中断机制,当程序出现错误,比如除零、非法内存访问时,便会产生信号事件。那么进程如何获知并响应该事件呢?Linux的进程是由内核管理的,内核会接收信号,并将其放入到相应的进程信号队列里面。当进程由于系统调用、中断或异常而进入内核态以后,从内核态回到用户态之前会检测信号队列,并查找到相应的信号处理函数。内核会为进程分配默认的信号处理函数,如果你想要对某个信号进行特殊处理,则需要注册相应的信号处理函数(如图1所示)。
图1 信号检测与处理流程(原图出自《Linux内核源代码情景分析》)
进程对信号异常的响应可以归结为以下几类:
对Native代码的崩溃,可以通过调用sigaction()注册信号处理函数来完成。
#include &signal.h&
int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact));
sigaction函数用于改变进程接收到特定信号后的行为。如果把第二、第三个参数都设为NULL,那么该函数可用于检查信号的有效性。
结构体sigaction包含了对特定信号的处理、信号所传递的信息、信号处理函数执行过程中应屏蔽掉哪些函数等等。
struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *);
sa_ int sa_ void (*sa_restorer)(void);
在一些体系上,sa_handler和sa_sigaction共用一个联合体(union),所以不要同时指定两个字段的值。
各参数的详细使用说明,请参考相关资料。
基于上面的分析,下面给出Native代码崩溃(即信号异常)捕获的代码片段,让大家有一个更直观的认识。
const int handledSignals[] = {
SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS
}; const int handledSignalsNum = sizeof(handledSignals) / sizeof(handledSignals[0]); struct sigaction old_handlers[handledSignalsNum]; int nativeCrashHandler_onLoad(JNIEnv *env) { struct memset(&handler, 0, sizeof(sigaction));
handler.sa_sigaction = my_
handler.sa_flags = SA_RESETHAND; for (int i = 0; i & handledSignalsN ++i) {
sigaction(handledSignals[i], &handler, &old_handlers[i]);
} return 1;
当Android应用程序加载so库的时候,调用nativeCrashHandler_onLoad会为SIGSEGV、SIGABRT、SIGFPE、SIGILL、SIGBUS通过sigaction注册信号处理函数my_sigaction。当发生Native崩溃并且发生前面几个信号异常时,就会调用my_sigaction完成信号处理。
notifyNativeCrash = (*env)-&GetMethodID(env, cls, &notifyNativeCrash&, &()V&); void my_sigaction(int signal, siginfo_t *info, void *reserved) { // Here catch the native crash
获取Native崩溃堆栈
Android没有提供像throwable.printStackTrace一样的接口去获取Native崩溃后堆栈信息,所以我们需要自己想办法实现。这里有两种思路可以考虑。
在本地调试代码时,我们经常通过查看LogCat日志来分析解决问题。对于发布的应用,在代码中执行命令“logcat -d -v threadtime”也能达到同样的效果,只不过是获取到了用户手机的logcat。当Native崩溃时,Android系统同样会输出崩溃堆栈到LogCat,那么拿到了LogCat信息也就拿到了Native的崩溃堆栈。
Process process = Runtime.getRuntime().exec(new String[]{&logcat&,&-d&,&-v&,&threadtime&}); String logTxt = getSysLogInfo(process.getInputStream());
在my_sigaction捕获到异常信号后,通知Java层代码,在Java层启动新的进程,并在新的进程中完成上面的操作。这里注意一定要在新的进程中完成,因为原有的进程马上就会结束。
网络上有一些对应这种思路的代码,但是在很多手机上都无法获得Native的崩溃堆栈。原因是对崩溃堆栈产生了破坏,使得相关信息并没有输出到logcat中。研究一下Android backtrace的底层实现以及Google Breakpad的源码,会帮助你解决这个问题。
Linux提供了Core Dump机制,即操作系统会把程序崩溃时的内存内容dump出来,写入一个叫做core的文件里面。Google Breakpad作为跨平台的崩溃转储和分析模块(支持Windows、OS X、Linux、iOS和Android等),便是通过类似的MiniDump机制来获取崩溃堆栈的。
通过Google Breakpad捕获信号异常,并将堆栈信息写入你指定的本地MiniDump文件中。下次启动应用程序的时候,便可以读取该MiniDump文件进行相应的操作,比如上传到后台服务器。当然,也可以修改Google Breakpad的源码,不写MiniDump文件,而是通过dumpCallback直接获得堆栈信息,并将相关信息通知到Java层代码,做相应的处理。
Google Breakpad是权威的捕获Native崩溃的方法,相关的使用方法可以查看官网文档。由于它跨平台,代码体量较大,所以建议大家裁剪源码,只保留Android相关的功能,保持自己APK的小巧。
视频观看地址:&(原文出处CSDN程序员杂志)
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:236369次
积分:3168
积分:3168
排名:第11484名
原创:34篇
转载:314篇
评论:23条
(2)(8)(4)(2)(4)(7)(2)(1)(3)(5)(1)(2)(1)(1)(2)(25)(3)(5)(9)(7)(3)(7)(7)(6)(9)(10)(9)(1)(2)(1)(7)(7)(3)(9)(7)(7)(8)(6)(3)(8)(6)(6)(5)(26)(18)(5)(70)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'主题 : 使用cocos2dx移植 android平台,怎么收集崩溃日志
级别: 新手上路
UID: 112924
可可豆: 75 CB
威望: 63 点
在线时间: 29(时)
发自: Web Page
来源于&&分类
使用cocos2dx移植 android平台,怎么收集崩溃日志&&&
    我想要实现移植android平台后可以收集到手机崩溃日志,网上搜集了很多帖子,只能单纯的收集android代码的错误,cocos2dx这边的错误信息收集不到还是会崩溃,求指点 
级别: 新手上路
UID: 112924
可可豆: 75 CB
威望: 63 点
在线时间: 29(时)
发自: Web Page
大神都来看看吧,求指点
级别: 新手上路
UID: 112924
可可豆: 75 CB
威望: 63 点
在线时间: 29(时)
发自: Web Page
大神都来看看吧,求指点
级别: 禁止发言
UID: 287492
发帖: 6884
可可豆: 546676 CB
威望: 546609 点
在线时间: 465(时)
发自: Web Page
用户被禁言,该主题自动屏蔽!
级别: 新手上路
UID: 264205
可可豆: 190 CB
威望: 144 点
在线时间: 289(时)
发自: Web Page
楼主知道了告诉我一声~~
级别: 侠客
UID: 148571
可可豆: 500 CB
威望: 341 点
在线时间: 198(时)
发自: Web Page
这个没试过,不过提供一个珍品给你,看看对你有用吗!
Do or not, just a moment!
关注本帖(如果有新回复会站内信通知您)
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 关注CVP公众号
扫一扫 浏览移动版摘要: 在android上开发c++应用, crash日志都是汇编码, 很难对应到c++代码中去. 通过此文, 你可以定位到程序崩溃时的C++代码, 精确查找问题.
作者: 知明所以
本文主要内容: 利用android的crash log来对c++开发的android应用进行错误定位.
容易稳定复现的BUG, 一般可以通过断点调试来解决. 如果测试人员也无法稳定复现, log就成了程序吊定位问题的救命稻草.
通用操作系统都有自己的日志系统, 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
06-20 15:54:35.431
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
06-20 15:54:35.511 23889 23889 I DEBUG
r4 760c1a48
r5 751e2440
r7 760c1a48
06-20 15:54:35.511 23889 23889 I DEBUG
r9 76c96f3c
sl 76c861c0
fp 76d94444
06-20 15:54:35.511 23889 23889 I DEBUG
sp 76d94430
lr 75a81bd8
pc 75a81bdc
cpsr 600f0010
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
676e702e6e776f6d
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
这密密麻麻的都是些神马, 是人看的么?
饿. 这个麻… 谁让你当程序猿! 让你当! 活该要看天书!
硬着头皮也要来, 我们就来讲讲怎么消化天书吧~
怎样获取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到上述的系统日志中.
下面是我正在开发的游戏一次崩溃后, 截取的日志( 插个广告, 全名斗地主下载地址:
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
06-20 15:54:35.431
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
06-20 15:54:35.511 23889 23889 I DEBUG
r4 760c1a48
r5 751e2440
r7 760c1a48
06-20 15:54:35.511 23889 23889 I DEBUG
r9 76c96f3c
sl 76c861c0
fp 76d94444
06-20 15:54:35.511 23889 23889 I DEBUG
sp 76d94430
lr 75a81bd8
pc 75a81bdc
cpsr 600f0010
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
676e702e6e776f6d
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
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 41c7ddc
06-20 15:54:35.511 23889 23889 I DEBUG
d20 3fefbb2
d21 3fdfdb
06-20 15:54:35.511 23889 23889 I DEBUG
d22 c00000
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
d26 3fdaa0f8fab43e33
d27 3fb43ad076b251ab
06-20 15:54:35.511 23889 23889 I DEBUG
d28 3fa15cb6bdc3c156
d29 3ec6cd878c3b46a7
06-20 15:54:35.511 23889 23889 I DEBUG
d30 3f65f3b6b9b97e01
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
: backtrace:
06-20 15:54:35.511 23889 23889 I DEBUG
pc 0089cbdc
/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::Texture2D::getContentSize() const+32)
06-20 15:54:35.511 23889 23889 I DEBUG
pc 0088f8dc
/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::Sprite::setTexture(std::string const&)+128)
06-20 15:54:35.511 23889 23889 I DEBUG
pc 007863dc
/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::ui::Button::loadTextureDisabled(std::string const&, cocos2d::ui::Widget::TextureResType)+336)
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
/system/lib/libc.so (free+12)
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so
06-20 15:54:35.511 23889 23889 I DEBUG
[anon:libc_malloc]
06-20 15:54:35.511 23889 23889 I DEBUG
[anon:libc_malloc]
06-20 15:54:35.511 23889 23889 I DEBUG
[anon:libc_malloc]
06-20 15:54:35.511 23889 23889 I DEBUG
/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::Sprite::setTexture(cocos2d::Texture2D*)+128)
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
[stack:2020]
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
[stack:2020]
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
[stack:2020]
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so
06-20 15:54:35.511 23889 23889 I DEBUG
[stack:2020]
06-20 15:54:35.511 23889 23889 I DEBUG
/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::Sprite::setTexture(std::string const&)+132)
06-20 15:54:35.511 23889 23889 I DEBUG
[stack:2020]
06-20 15:54:35.511 23889 23889 I DEBUG
[anon:libc_malloc]
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.511 23889 23889 I DEBUG
06-20 15:54:35.521 23889 23889 I DEBUG
[anon:libc_malloc]
06-20 15:54:35.521 23889 23889 I DEBUG
[anon:libc_malloc]
06-20 15:54:35.521 23889 23889 I DEBUG
[stack:2020]
06-20 15:54:35.521 23889 23889 I DEBUG
/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so (cocos2d::ui::Button::loadTextureDisabled(std::string const&, cocos2d::ui::Widget::TextureResType)+340)
06-20 15:54:35.521 23889 23889 I DEBUG
06-20 15:54:35.521 23889 23889 I DEBUG
06-20 15:54:35.521 23889 23889 I DEBUG
[stack:2020]
06-20 15:54:35.521 23889 23889 I DEBUG
[anon:libc_malloc]
06-20 15:54:35.521 23889 23889 I DEBUG
[stack:2020]
06-20 15:54:35.521 23889 23889 I DEBUG
[anon:libc_malloc]
06-20 15:54:35.521 23889 23889 I DEBUG
06-20 15:54:35.521 23889 23889 I DEBUG
/system/lib/libc.so (free+12)
06-20 15:54:35.521 23889 23889 I DEBUG
06-20 15:54:35.521 23889 23889 I DEBUG
/data/app-lib/com.guangyou.ddgame-1/libcocos2dcpp.so
06-20 15:54:35.521 23889 23889 I DEBUG
[anon:libc_malloc]
06-20 15:54:35.521 23889 23889 I DEBUG
[anon:libc_malloc]
06-20 15:54:35.521 23889 23889 I DEBUG
[stack:2020]
06-20 15:54:35.521 23889 23889 I DEBUG
/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-20 15:54:35.521 23889 23889 I DEBUG
06-20 15:54:35.521 23889 23889 I DEBUG
[anon:libc_malloc]
06-20 15:54:35.521 23889 23889 I DEBUG
06-20 15:54:35.521 23889 23889 I DEBUG
: memory near r0:
06-20 15:54:35.521 23889 23889 I DEBUG
76d94438 76a66184 760c1a48 76d9447c 75a748e0
06-20 15:54:35.521 23889 23889 I DEBUG
76d94448 76d944ec 793ff0e8 76a72c54
06-20 15:54:35.521 23889 23889 I DEBUG
06-20 15:54:35.521 23889 23889 I DEBUG
: memory near r4:
06-20 15:54:35.521 23889 23889 I DEBUG
75ee318c 75ee3194 75ee319c
06-20 15:54:35.521 23889 23889 I DEBUG
75f9a1f4 75f4ee5c 75e8ea0c
下面来逐行解读:
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, 表示段错误, 是最常见的信号.(, )
5. 接下来的部分是系统寄存器的dump信息.
rX(X=[0~9])
代表整数寄存器
dX(X=[0~31])
是浮点指针寄存器
fp (or r11)
指向当前正在执行的函数的堆栈底.
ip (or r12)
一个寄存器, 我也没弄明白是干啥的.
sp (or r13)
当前正在执行的函数的堆栈顶.(跟fp相对应)
lr (or r14)
. 简单来说, 当当前指令执行完了, 就会从这个寄存器获取地址, 来知道需要返回到哪里继续执行.
pc (or r15)
program counter. 存放下一条指令的地址
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
ndk-stack -sym &path& [-dump &path&]
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
/data/data/com.packtpub.droidblaster/lib/libdroidblaster.so: Routine run in /home/packt/Project/Chapter11/DroidBlaster_Part11/jni/EventLoop.cpp:49
Stack frame #03
/data/data/com.packtpub.droidblaster/lib/libdroidblaster.so: Routine android_main in /home/packt/Project/Chapter11/DroidBlaster_Part11/jni/Main.cpp:31
熟悉的代码出现啦~~
Written with .
阅读(...) 评论()}

我要回帖

更多关于 cocos2dx js android 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信