[教程] Android Native内存泄漏检测方法

时间:2024-01-20 20:33:39

转载请注明出处:https://www.cnblogs.com/zzcperf/p/9563389.html

Android 检测 C/C++内存泄漏的方法越来越简便了,下面列举一下不同场景下检测C/C++内存泄漏的方法。

在介绍检查方法之前,先把一个技巧说在前头。因为打开检测开关,会严重影响手机性能,所以最好使用32位手机来检测,32位手机会顺畅一点。

Android 7.x / 8.x(针对root设备,调试安卓APP

1. 准备一个userdebug或eng版本手机,尽量选择32bit机器,64bit设备会非常卡,libc_malloc_debug.so需要编译进去,下载native_heapdump_viewer.py脚本备用

2. 打开debug开关。

1)如果是Android 8.x,执行以下命令

adb shell setprop wrap.<APP_PACKAGE_NAME> '"LIBC_DEBUG_MALLOC_OPTIONS=backtrace"'
adb shell am force-stop <APP_PACKAGE_NAME>

2)如果是Android 7.x (8.x 也可以用),执行以下命令,其中app_process照写,不需要针对调试的app更改

adb root
adb shell stop
adb shell setprop lib.debug.malloc.program app_process
adb shell setprop lib.debug.malloc.options "\"backtrace leak_track\""
adb shell start

3. 执行重现路径N次

4. 执行以下命令,其中/path/to/symbols/是指存放带有符号信息so文件的文件夹,默认是$ANDROID_PRODUCT_OUT/symbols。

adb shell am dumpheap -n <PID_TO_DUMP> /data/local/tmp/heap.txt

adb pull /data/local/tmp/heap.txt

python development/scripts/native_heapdump_viewer.py --html --symbols /path/to/symbols/ heap.txt > heap_info.html

5. 不重启手机,继续重复第三、第四步,即再重现N次,抓出累计重现了2N次的log,最后对比两次生成的heap_info.html

Android 5.x - 7.x(针对root设备,调试Native进程)

Google的调试方法可以参考这里,Google的方法在不断完善中,遇到问题或需要更灵活的调试方法时,可以使用下面的库。

ChkMemLeak库只有一个函数checkLeak,每次调用该函数,都输出当前进程尚未释放的内存。

对比多次输出结果,排查可疑的内存泄漏。

1. 将ChkMemLeak库添加到系统代码中。

2. 在需要调试的代码中包含头文件,调用checkLeak();在Android.mk(或.bp)动态库libcheckleak。

注意不要在线程的死循环中调用,否则会导致性能问题。

3. 打开debug开关

如果是Android 7.x / 8.x,执行以下命令

adb root
adb shell stop
adb shell setprop lib.debug.malloc.program 进程名
adb shell setprop lib.debug.malloc.options "\"backtrace leak_track\""
adb shell start

如果是Android 5.x / 6.x,执行以下命令

adb root
adb shell setprop libc.debug.malloc=1
adb shell stop
adb shell start

4. 执行调用checkLeak()的操作路径,每调用一次,都会在 /data 目录生成 checkleak_PID_timestamp.csv

size, duplications, backtrace三列分别是单次分配大小、分配次数,调用栈

找到可疑的分配路径后,使用addr2line工具找到对应的代码位置。

Android 4.x或之前版本(针对root设备,调试Native进程)

这么老的OS应该很少用了,解析调用栈的头文件是/android/system/core/include/corkscrew/backtrace.h

有需要的同学可以参照ChkMemLeak实现一下。