前言
最近写C++代码,老是担心代码存在内存泄露,胆战心惊的,Andorid中Java层代码内存泄露可以借助leakcanary进行检测;找了一番,找到了PC上C++上的内存泄露检测库LeakTracer,于是再找了下,找到了Android上的移植版。
首先建立一个项目,在根目录下建立thirdparty目录,进入该目录,clone相关库代码
1 | git clone git@github.com:lizhangqu/LeakTracer.git |
在项目src/main/cpp下建立CMakeLists.txt,内容如下
1 | project(Test) |
建立src/main/cpp/include/native.h和src/main/cpp/native.cpp文件
native.h
1 | // |
native.cpp
1 |
|
编写test函数,简单进行内测泄露检测
1 | class MemoryTest { |
运行程序后调用test函数,将/sdcard/leaks.out pull到项目根目录
1 | adb pull /sdcard/leaks.out |
其内容类似如下内容
1 | # LeakTracer report diff_utc_mono=1496511718.682943 |
借助thirdparty/LeakTracer/helper/leak-analyze-addr2line工具还原内测泄露堆栈。
进入项目根目录,执行leak-analyze-addr2line
1 | ./thirdparty/LeakTracer/helpers/leak-analyze-addr2line ./library/build/intermediates/cmake/debug/obj/armeabi/libtest-jni.so ./leaks.out |
在mac上,会出现一个错误,原因是leak-analyze-addr2line中用到了addr2line工具,而mac上如果没有此工具,就会报错,错误如下:
解决方法很简单,将ndk目录中的arm-linux-androideabi-addr2line拷到./thirdparty/LeakTracer/helpers/下,并重命名为addr2line,然后将./thirdparty/LeakTracer/helpers/加到环境变量中,如下代码
1 | cp $ANDROID_NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-addr2line ./thirdparty/LeakTracer/helpers/addr2line |
$ANDROID_NDK_HOME表示ndk的根目录。
之后再次调用命令
1 | ./thirdparty/LeakTracer/helpers/leak-analyze-addr2line ./library/build/intermediates/cmake/debug/obj/armeabi/libtest-jni.so ./leaks.out |
这时候输出如下
native.cpp:15行出现泄露,找到15行对应的代码,即如下代码出现泄露
1 | MemoryTest *memoryTest = new MemoryTest; |
加入delete代码,再跑一次
1 | MemoryTest *memoryTest = new MemoryTest; |
输出如下
发现之前的泄露不见了
最后,值得注意的是,要想使用LeakTracer需要保留so足够多的debug信息,否则可能不能正常检测。
项目Demo地址见NDKMemoryLeakSample