遇到c ++的异常,我们该如何快速分析

image

技术文穿插着更新,一直爱你们的明哥。今天更新个出现c++异常,怎么才能快速高效 的去定位,分析出原因。剩下的,便是慢慢求证过程,最终解决问题。

1找到异常堆栈

2解析堆栈信息

3对应源码分析

4解决问题

1

当出现c ++的异常时,很多时候进程是直接退出,不会像java的那样,弹出一个异常框出来,此时在log中会出现如下一堆信息

image

这段信息的内容,该如何分析呢?且往下慢慢看来。

Build fingerprint: ‘XXXXXXXX/xxxxxx/:user/release-keys’  初步定位版本信息

pid: 10928 进程号

tid: 10939 线程号

如果两个不一样,说明是在异步线程,分析时就会多一个异步操作出现的数据不一致故障

name: Binder:10928_1线程名字 ,binder 出现之后,就表示是个跨进程的调用,此进程作为服务端,进行响应客户端的方法调用。 

com.soundrecorder:remote <<<包名  

signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x10

异常类别,一般sigal 11  segv_maperr 这种大概看一下,主要我们围绕着异常地址fault addr 0x10 ,当看到这种小于100以内的值,就能初步定位属于引用一个指针指向的结构体中的一个属性时,产生了异常

 r0 00000000  r1 adf00a7c  r2 00000000  r3 b4100b39    r4 00000000  r5 adf00df0  r6 adf00b90  r7 adf00b50    r8 adf00df0  r9 ae00e400  sl ae00e48c  fp adf00b1c    ip ab757a88  sp adf00a68  lr ab7309b3  pc b55f6cb8  cpsr 400b0030

寄存器值,我们关注r0 ,r0 代表着this,所以这里可以看到this为空,我们引用了它的一个属性,引起的故障

r1- r4 代表着四个参数,后续再多的参数,会在r5里面以堆栈出现,一边只会关注前四个即可。

sp代表当前栈指向的位置 lr代表当前返回的方法位置

2

backtrace:    #00 pc 00096cb8  /system/lib/libmedia.so (_ZN7android13MediaRecorder15getMaxAmplitudeEPi+3)    #01 pc 0002e9af  /system/lib/libmedia_jni.so

当异常出现后,backtrace就比较关键了,它是可以打印出当前线程的方法调用栈,从异常点向前一直打印。我们一般关注这块,要去看跟我们开发更近的so 库,比如这里就是libmedia.so ,libart.so就不是我们考虑的,如果是libc.so 一样不做考虑,我们要看的是除掉公共库之外的。

这里pc 00096cb8  意思为,异常点在/system/lib/libmedia.so的偏移00096cb8位置上,那么我们就要去打开这个so库,进行分析定位。

后面的(_ZN7android13MediaRecorder15getMaxAmplitudeEPi+3) 就是异常时,调用的方法名字,这里用了c++命名规则,实际中我们拆出熟悉的字段

这里就是android  MediaRecorder getMaxAmplitude 于是就是我们方法名字的关键字搜索了。

我们可以使用addr2line工具进行分析(此工具在NDK的tools下面,关于使用方法,参考https://www.cnblogs.com/274914765qq/p/4591940.html

我们这里使用IDA逆向工具,进行反编译so

然后我们从手机上将 /system/lib/libmedia.so 导出来,然后用IDA pro 进行打开,当然了 你也可以用addr2line和objdump进行操作,不过是命令行,界面不太友好,于是我们用IDA 强大的反编译工具进行。

打开后,出现的界面如下

image

前面讲解了 #00 pc 00096cb8  /system/lib/libmedia.so (_ZN7android13MediaRecorder15getMaxAmplitudeEPi+3)

就是说出现异常的时候,是在libmedia.so 库的相对 00096cb8位置 ,getMaxAmplitude方法的第三行。

于是我们定位到这一行(使用G快速进入jump to address ,输入 96cb8 ,来到我们的异常位置)

image

.text:00096CB8                 LDR             R0, [R4,#0x10]

可以看到我们出现异常的时候,确实是在这个方法了,然后我们可以进一步搜索源码,使用 getMaxAmplitude来进行定位。

3

通过过滤,很快我们会定位到MediaRecorder.cpp文件中

图片4.png

根据代码,然后根据我们分析,去推这个mMediaRecorder如何赋值,如何释放的。然后我们这里有个基础推理就是,我们异常的时候,是在一个binder线程,那么就可以去从多线程不同步去做假设,更好的去推出产生原因,然后进行修复。

4

本节主要从分析的方向,将一个异常的分析思路,进行展开。除此之外,我们在分析问题时,要去看其他线程的堆栈,以及log信息,将输出的log信息 和 自己的分析进行验证,进一步确定异常路径。

猜你喜欢

转载自blog.csdn.net/a332324956/article/details/80495020