如何分析native memory leak
分析native程序发生内存泄漏问题,就需要对每一笔内存申请做记录,释放内存时清除记录,然后在认为存在内存泄漏时将记录提取出来分析,看看在哪段代码存在申请的内存没有释放。
不过native进程申请内存的方法很多,可以直接通过mmap映射内存,也可以通过传统的堆分配函数malloc分配内存。这里我们只关注通过堆分配函数引起的内存泄漏。
Android有提供这部分内存泄漏的调试方法,但这个仅适用于app进程,对于其他native进程则需要另外的方法。
[
1. 打开内存监控功能(
必须使用eng或userdebug版本)。
Android有提供堆调试功能
打开方法如下:
KK及以前版本:开机后用adb输入:
adb shell setprop persist.libc.debug.malloc 15
adb shell setprop persist.libc.debug15.prog mediaserver
adb shell setprop persist.debug15.config 0x24003024
adb reboot
adb shell setprop persist.libc.debug15.prog mediaserver
adb shell setprop persist.debug15.config 0x24003024
adb reboot
或
adb shell setprop persist.libc.debug.malloc 1
adb reboot
adb reboot
L及之后版本:在vendor/mediatek/proprietary/external/aee/config_external/init.aee.customer.rc添加:
on init
export LD_PRELOAD libsigchain.so:libudf.so
重新打包bootimage并下载, 开机后用adb输入:
export LD_PRELOAD libsigchain.so:libudf.so
重新打包bootimage并下载, 开机后用adb输入:
adb shell setprop persist.libc.debug.malloc 15
adb shell setprop persist.libc.debug15.prog mediaserver
adb shell setprop persist.debug15.config 0x4a003024
adb reboot
adb shell setprop persist.libc.debug15.prog mediaserver
adb shell setprop persist.debug15.config 0x4a003024
adb reboot
O及之后版本:直接adb:
adb shell "echo libc.debug.malloc.options="backtrace=8" >> /data/local.prop"
adb shell "echo libc.debug.malloc.program= mediaserver >> /data/local.prop"
adb shell "chmod 644 /data/local.prop"
adb reboot
adb shell "echo libc.debug.malloc.program= mediaserver >> /data/local.prop"
adb shell "chmod 644 /data/local.prop"
adb reboot
其中红字部分修改为要监控的
可执行文件名。
2. 检查是否存在内存泄漏。
打开mtklogger,不断通过adb shell procrank -u > procrank.txt查看当前系统内存的使用情况。
当看到被监控的进程占用内存(USS字段)超过了正常值很多,则可能存在内存泄漏。
3. 得到该进程内存使用分布情况($pid为被监控进程pid)
adb shell dumpsys meminfo $pid >meminfo_$pid.txt
adb shell procmem $pid > procmem_$pid.txt
adb shell dumpsys meminfo $pid >meminfo_$pid.txt
adb shell procmem $pid > procmem_$pid.txt
4. 抓取该进程的coredump。
adb shell kill -5 $pid
5. 抓取coredump和mtklog。可以用GAT的bugreport功能一键抓取log。将以上这些抓取的coredump和log提供到e-service给MTK分析。
6. 现在这种问题也可以自行分析,用E-Consulter(mtk online的工具栏搜索得到)分析,会给出分析报告,如果存在超过128M以上的泄漏,那么分析报告会提示如下:
== C堆检查 == 分配器: dlmalloc, 最多允许使用: 4GB, 最多使用: 188MB, 当前使用: 166MB, 泄露阈值: 128MB, 调试等级: 1 该堆已分配超过128MB (可能存在内存泄露), 以下列出分配最大尺寸和次数的调用栈: 大小: 1184字节, 已分配: 134604次 分配调用栈: libc_malloc_debug_leak.so 0x40D5ECD4() + 16 libc_malloc_debug_leak.so leak_malloc() + 43 libc.so malloc() + 18 libsqlite.so sqlite3MemMalloc() + 14 <external/sqlite/dist/sqlite3.c:15298> libsqlite.so mallocWithAlarm() + 86 <external/sqlite/dist/sqlite3.c:18862> libsqlite.so sqlite3Malloc() + 16 <external/sqlite/dist/sqlite3.c:18895> ...... == 栈结束 == 大小: 1184字节, 已分配: 5149次 分配调用栈: libc_malloc_debug_leak.so 0x40D5ECD4() + 16 libc_malloc_debug_leak.so leak_malloc() + 43 libc.so malloc() + 18 libsqlite.so sqlite3MemMalloc() + 14 <external/sqlite/dist/sqlite3.c:15298> libsqlite.so mallocWithAlarm() + 86 <external/sqlite/dist/sqlite3.c:18862> ...... == 栈结束 == 大小: 1048584字节, 已分配: 1次 分配调用栈: libc_malloc_debug_leak.so 0x40D5ECD4() + 16 libc_malloc_debug_leak.so leak_malloc() + 43 libc.so malloc() + 18 libsqlite.so sqlite3MemMalloc() + 14 <external/sqlite/dist/sqlite3.c:15298> libsqlite.so mallocWithAlarm() + 86 <external/sqlite/dist/sqlite3.c:18862> libsqlite.so sqlite3Malloc() + 16 <external/sqlite/dist/sqlite3.c:18895> ...... == 栈结束 ==