NDK开发(四)--NDK调试
崩溃日志分析
在ndk崩溃的时候,如果是习惯JAVA 开发的同学,可能会毫无头绪,因为其崩溃信息并不像JAVA那样清晰,如果不知道各个部分的错误信息是代表啥意思,可能在出现问题的时候,不知道从何入手解决。
-w1355
上面是一个比较全的NDK崩溃堆栈。基本上一个崩溃日志可以分为三部分:错误信号
,寄存器信息
,方法调用栈
。
- 1、错误信号
从错误信号里面,一般会告知,是哪种类型的异常,譬如上面的错误,提示了,导致的原因是空指针。
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 Cause: null pointer dereference
- 2、寄存器信息
暂时不依赖这部分分析。
- 3、方法调用栈
是调用了哪个方法导致的异常。有一系列的调用堆栈信息。
常见的NDK崩溃
- 1、野指针
指向了一个无效的地址
void errorAddressCrash() {
//没有分配地址
int *p;
//进行赋值
*p = 1;
}
解决方式是在定义的时候,需要进行初始化;在释放了指针指向的内存后,要把该指针置为NULL
- 2、空指针
//空指针异常 void nullPointCrash() { int *p = NULL; *p = 1; printf("%d\n", *p); }
解决方式一般是在使用的时候,增加空判断,如上面的栗子,增加if (p != NULL){}
- 3、数组越界
这种比较容易理解,譬如定义了int data[10];但我们访问了data[11];
解决方式就是在使用之前,对其长度进行判断。
- 4、内存泄露
C语言不像JAVA 一样,需要自己进行内存管理,所以在使用的时候,需要注意内存释放。内存泄露一般都是在使用之后没有进行释放.
- 5、堆栈溢出
当使用了大量的局部引用而没有及时释放的话,就可能出现局部引用表溢出,所以变量用完以后需要回收一下
local reference table overflow (max=512)
如上面的解决方式可以是(*env)->DeleteLocalRef(env, jobject);
符号表
符号表就是内存地址与函数名、文件名、行号的映射表。如下,在AS打包的时候,一般都会生成两个以上的so,其中obj 目录下的so 是带符号表的,另外两个目录下的so 是不带符号表的。
-w1349
另外,带符号表的和不带符号表的so的体积,会有较大的差别。
app/build/intermediates/cmake/debug/obj/x86/目录下的
→ ls|xargs du -sh [07cec0a]
0B arm64-v8a
0B armeabi-v7a
1.1M x86
0B x86_64
app/build/intermediates/transforms/stripDebugSymbol/debug/0/lib/x86/目录下的
ls|xargs du -sh [07cec0a]
200K x86
可以看到,两个体积相差将近5倍左右。