随便在哪,用下空指针,在ddms log中都能打印出具体位置来,很好分析;界面上只是打印个异常提醒;
第二类:native 中使用空指针
---WebCoreFrameBridge.cpp文件LoadData函数
pFrame = NULL;--add
1.界面上没有提示,只是闪立下,回到之前操作界面;通过ddms观察,应用已经重启立;
2. log和 /data/tombstones/中都有 tombstone文件;
3. tomestone的关键信息,
pid: 894, tid: 975 >>> com.android.settings <<< #这些信息也可以帮助分析;
#00 pc 000cd968 /system/lib/libwebcore.so
#01 lr a84c9593 /system/lib/libwebcore.so
4.使用addr2line找空指针位置;
./arm-eabi-addr2line -C -f -e libwebcore.so 000cd968
WebCore::FrameLoader::load(WebCore::ResourceRequest const&, WebCore::SubstituteData const&, bool)
/external/webkit/WebCore/loader/FrameLoader.cpp:2033
在使用pFrame->loader()->load(request, substituteData, false);时,pFrame为空;定位的是实现的地方;
/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin$ ./arm-eabi-addr2line -C -f -e libwebcore.so a84c9593
??
??:0
但调用的地方,并不能定位;对找原因,还是很困难;
补充转
2 确认了问题的基本点,下面就是开始看蓝色的部分了。
这个蓝色不分是从#00-->#XX 表面上看是从上往下的增长,其实坑爹啊,它所显示的程序的执行流程,恰恰是从下往上的也就是实际的执行顺序是#XX-->#00。
所以一开始我们的目的是分析第一个出现问题的动态连接库
#15 pc 0001173c /system/lib/libc.so
a 首先按图索骥,找到你的目标,libc.so这个一般会在你编译完的目标目录下,也就是out/target/product/your_pro/system/lib这个目录下。
b 一般你如果用的是还像样的linux系统,会有个地址解析的命令addr2line,负责解析动态连接库的(如果你是悲剧,没有这个命令,那好吧, google早就预料到会有象你这样的悲剧人,他们在prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-addr2line,给您准备了个,咋就用这个吧,功能一样,没啥区别)
addr2line -e -f libc.so 0001173c 红色是你的目标库,绿色是你出问题的地址,看看#15这行
结果出现:??pthread_create
??:0
恩,好了问题应该出在这个函数中,认为大功告成了?我,呸,还早呢。这个只是告诉你函数入口,至于具体执行到这个函数的哪个地方挂了,还得再看。
c 找到了是哪个部分出了问题,下面就是开启显微镜,看看谁搞的东东。
使用objdump -S -D libc.so > deassmble_libc.txt 反汇编下你的动态连接库文件,并且将它写入一个文件中。
打开这个反汇编过后的重定向文件,在查询的时候输入1173c这个偏移地址,你会看到在茫茫人海中
00011684 <pthread_create>:
11684: e92d4ff0 push {r4, r5, r6, r7, r8, r9, sl, fp, lr}
11688: e24dd01c sub sp, sp, #28 ; 0x1c
1168c: e1a06001 mov r6, r1
11690: e1a08002 mov r8, r2
11694: e1a09003 mov r9, r3
11698: e3a04001 mov r4, #1 ; 0x1
1169c: e59f521c ldr r5, [pc, #540] ; 118c0 <pthread_create+0x23c>
116a0: e58d000c str r0, [sp, #12]
116a4: eb009a35 bl 37f80 <strncmp+0x20>
116a8: e59f2214 ldr r2, [pc, #532] ; 118c4 <pthread_create+0x240>
116ac: e1a03000 mov r3, r0
116b0: e1a01004 mov r1, r4
116b4: e593c000 ldr ip, [r3]
116b8: e3a0003c mov r0, #60 ; 0x3c
116bc: e08f3005 add r3, pc, r5
116c0: e7933002 ldr r3, [r3, r2]
116c4: e5834000 str r4, [r3]
116c8: e58dc010 str ip, [sp, #16]
116cc: eb009a3b bl 37fc0 <strncmp+0x60>
...
1173c: ebffec2b bl c7f0 <__pthread_clone>-->就是他了,对你成功了。
...
这个是ARM汇编,需要你翻译成对应的C函数去看,这里我就不做解释了,照着前面的步骤,
对上面中#15-->#00 一共16行慢慢去找,直到找到#00行的问题函数,其实,最后一个#00行的是最重要的(前面不找也行,但是可以多给你提供问题信息,和流程),因为他是第一目击者,也是Crash前的第一现场。所以找到这个函数很重要,假设我们最后经过万里长针发现#00的出错的地方是pXX->member挂了(MD,我经常遇到这种问题)。
那么你可以怀疑两个地方:
1 您的指针是空指针,但是现实与理想总是十万八千里,多数情况下很少出现,而且你分析代码后,也会对自己说怎么可能。绝大多数情况下,从我的经验来讲,很少会有空指针这种低级错误,但是不排除哪个2货出现了这么个问题。如果是这个问题,那么恭喜你,你很幸运。
2 还有就是怀疑越界和内存地址被挤占。就拿我以前的经验,指针不是空,但是根据汇编码看,是访问成员变量挂了,这个地址肯定是被占用了。
针对第2种比较恶心的情况,就需要你看整个log的流程了,需要你看下主要的mainlog关于出现crash前的动作,看看是哪个孙子占用的,以最近原则为先,从下往上看,唉,说句实在话,李白的一句话可以形容整个过程:"蜀道难,难于上青天啊"。工作量大,而且要细致。我也没什么办法。。。