Android malloc debug定位native内存问题(主要是内存泄漏)

android sources全局指导坐镇

https://source.android.com/devices/tech/debug/native-memory

一直没有实践native进程的内存泄漏问题的debug,网上也一直没找到有用的。直到遇到heapsnap,发现真是有用,至此一块心病也是解决了。再加上之前用asan来分析userspace的内存问题,可以说稳定性这块关于内存的算是有初步的把握了。后续就是需要对内核关于内存的优化有更多的学习和总结。

验证Android版本为P

1.用malloc debug发现内存非法使用问题
setprop libc.debug.malloc.options backtrace
setprop libc.debug.malloc.program vendor/bin/test

11-15 10:29:51.406  4573  4573 I malloc_debug: ./vendor/bin/test: Run: 'kill -47 4573' to dump the backtrace.
11-15 10:29:51.408  4573  4573 I libc    : ./vendor/bin/test: malloc debug enabled
11-15 10:29:51.410  4573  4573 D         : test main
11-15 10:29:51.410  4573  4573 D TEST    : test begin1
11-15 10:29:51.410  4573  4573 D TEST    : double free
11-15 10:29:51.410  4573  4573 E TEST    : afte free test1: -1345756352
11-15 10:29:51.410  4573  4573 E TEST    : afte free test2 99
11-15 10:29:51.410  4573  4573 E malloc_debug: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-15 10:29:51.410  4573  4573 E malloc_debug: +++ ALLOCATION 0xafc8c018 UNKNOWN POINTER (free)
11-15 10:29:51.410  4573  4573 E malloc_debug: Backtrace at time of failure:
11-15 10:29:51.410  4573  4573 E malloc_debug:           #00  pc 00000d08  /vendor/lib/libtest.so (doTest()+71)
11-15 10:29:51.410  4573  4573 E malloc_debug:           #01  pc 00088f54  /system/lib/libc.so (__libc_init+47)
11-15 10:29:51.410  4573  4573 E malloc_debug:           #02  pc 00000ba2  /vendor/bin/test
11-15 10:29:51.411  4573  4573 E malloc_debug: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
11-15 10:29:51.411  4573  4573 E TEST    : afte free 2 times

an.xi@droid01:/mnt/fileroot/an.xi/p$ addr2line -ife out/target/product/ampere/symbols/vendor/lib/libtest.so 00000d08
_Z6doTestv
vendor/amlogic/common/system/libtest/testlib.cpp:34


 30     free (buf_);
 31     ALOGE("afte free test1: %d\n",buf_->test1);
 32     buf_->test2 = 99;
 33     ALOGE("afte free test2 %d\n",buf_->test2);
 34     free (buf_); -----
 35     ALOGE("afte free 2 times \n");

检测到的是两次free,并且use after free没有检测出来,因为这只是打栈。


2.用malloc debug发现内存泄漏
setprop libc.debug.malloc.options leak_track
setprop libc.debug.malloc.program vendor/bin/test

11-15 10:39:42.332  4594  4594 I malloc_debug: vendor/bin/test: Run: 'kill -47 4594' to dump the backtrace.
11-15 10:39:42.334  4594  4594 I libc    : vendor/bin/test: malloc debug enabled
11-15 10:39:42.336  4594  4594 D         : test main
11-15 10:39:42.336  4594  4594 D TEST    : test begin1
11-15 10:39:42.336  4594  4594 D TEST    : double free
11-15 10:39:42.336  4594  4594 E TEST    : afte free test1: 101
11-15 10:39:42.336  4594  4594 E TEST    : afte free test2 99
11-15 10:39:42.336  4594  4594 E TEST    : afte free 2 times
11-15 10:39:42.336  4594  4594 E malloc_debug: +++ vendor/bin/test leaked block of size 48 at 0xa7b1a540 (leak 1 of 5)
11-15 10:39:42.336  4594  4594 E malloc_debug: Backtrace at time of allocation:
11-15 10:39:42.337  4594  4594 E malloc_debug:           #00  pc 00009b66  /system/lib/vndk-sp-28/libutils.so (android::SharedBuffer::alloc(unsigned int)+13)
11-15 10:39:42.337  4594  4594 E malloc_debug:           #01  pc 0000d55e  /system/lib/vndk-sp-28/libutils.so (android::VectorImpl::_grow(unsigned int, unsigned int)+285)
11-15 10:39:42.337  4594  4594 E malloc_debug:           #02  pc 0000daba  /system/lib/vndk-sp-28/libutils.so (android::VectorImpl::add(void const*)+13)
11-15 10:39:42.337  4594  4594 E malloc_debug:           #03  pc 0000e40e  /system/lib/vndk-sp-28/libutils.so (android::add_sysprop_change_callback(void (*)(), int)+93)
11-15 10:39:42.337  4594  4594 E malloc_debug: +++ vendor/bin/test leaked block of size 20 at 0xa7b08ac8 (leak 2 of 5)
11-15 10:39:42.337  4594  4594 E malloc_debug: Backtrace at time of allocation:
11-15 10:39:42.337  4594  4594 E malloc_debug:           #00  pc 0004365c  /system/lib/vndk-sp-28/libc++.so (operator new(unsigned int)+15)
11-15 10:39:42.337  4594  4594 E malloc_debug:           #01  pc 0000e3d4  /system/lib/vndk-sp-28/libutils.so (android::add_sysprop_change_callback(void (*)(), int)+35)
11-15 10:39:42.337  4594  4594 E malloc_debug: +++ vendor/bin/test leaked block of size 5 at 0xa7b0c010 (leak 3 of 5)
11-15 10:39:42.337  4594  4594 E malloc_debug: Backtrace at time of allocation:
11-15 10:39:42.337  4594  4594 E malloc_debug:           #00  pc 0000c508  /system/lib/liblog.so
11-15 10:39:42.337  4594  4594 E malloc_debug:           #01  pc 0000c36e  /system/lib/liblog.so (__android_log_is_loggable_len+9)
11-15 10:39:42.337  4594  4594 E malloc_debug:           #02  pc 0000724e  /system/lib/liblog.so
11-15 10:39:42.337  4594  4594 E malloc_debug:           #03  pc 00006b6a  /system/lib/liblog.so (__android_log_buf_write+249)
11-15 10:39:42.337  4594  4594 E malloc_debug:           #04  pc 00006c9e  /system/lib/liblog.so (__android_log_print+65)
11-15 10:39:42.337  4594  4594 E malloc_debug:           #05  pc 00000c76  /vendor/lib/libtest.so (doTest()+13)
11-15 10:39:42.337  4594  4594 E malloc_debug:           #06  pc 00088f54  /system/lib/libc.so (__libc_init+47)
11-15 10:39:42.337  4594  4594 E malloc_debug:           #07  pc 00000ba2  /vendor/bin/test
11-15 10:39:42.337  4594  4594 E malloc_debug: +++ vendor/bin/test leaked block of size 4 at 0xa7b0c008 (leak 4 of 5)
11-15 10:39:42.337  4594  4594 E malloc_debug: Backtrace at time of allocation:
11-15 10:39:42.338  4594  4594 E malloc_debug:           #00  pc 0005b010  /system/lib/libc.so
11-15 10:39:42.338  4594  4594 E malloc_debug:           #01  pc 000223ea  /system/lib/libc.so (newlocale+93)
11-15 10:39:42.338  4594  4594 E malloc_debug:           #02  pc 00069142  /system/lib/libc++.so
11-15 10:39:42.338  4594  4594 E malloc_debug:           #03  pc 0006ea34  /system/lib/libc++.so (std::__1::locale::__global()+119)
11-15 10:39:42.338  4594  4594 E malloc_debug:           #04  pc 0006eab4  /system/lib/libc++.so (std::__1::locale::locale()+3)
11-15 10:39:42.338  4594  4594 E malloc_debug:           #05  pc 0004d82c  /system/lib/libc++.so (std::__1::basic_streambuf>::basic_streambuf()+15)
11-15 10:39:42.338  4594  4594 E malloc_debug:           #06  pc 00054482  /system/lib/libc++.so
11-15 10:39:42.338  4594  4594 E malloc_debug:           #07  pc 000540d8  /system/lib/libc++.so (std::__1::ios_base::Init::Init()+23)
11-15 10:39:42.338  4594  4594 E malloc_debug:           #08  pc 0003276a  /system/lib/libc++.so
11-15 10:39:42.338  4594  4594 E malloc_debug: +++ vendor/bin/test leaked block of size 4 at 0xa7b0c028 (leak 5 of 5)
11-15 10:39:42.339  4594  4594 E malloc_debug: Backtrace at time of allocation:
11-15 10:39:42.340  4594  4594 E malloc_debug:           #00  pc 0005b010  /system/lib/libc.so
11-15 10:39:42.340  4594  4594 E malloc_debug:           #01  pc 000223ea  /system/lib/libc.so (newlocale+93)
11-15 10:39:42.340  4594  4594 E malloc_debug:           #02  pc 00069102  /system/lib/vndk-sp-28/libc++.so
11-15 10:39:42.340  4594  4594 E malloc_debug:           #03  pc 0006e9f4  /system/lib/vndk-sp-28/libc++.so (std::__1::locale::__global()+119)
11-15 10:39:42.340  4594  4594 E malloc_debug:           #04  pc 0006ea74  /system/lib/vndk-sp-28/libc++.so (std::__1::locale::locale()+3)
11-15 10:39:42.340  4594  4594 E malloc_debug:           #05  pc 0004d7ec  /system/lib/vndk-sp-28/libc++.so (std::__1::basic_streambuf>::basic_streambuf()+15)
11-15 10:39:42.340  4594  4594 E malloc_debug:           #06  pc 00054442  /system/lib/vndk-sp-28/libc++.so
11-15 10:39:42.340  4594  4594 E malloc_debug:           #07  pc 00054098  /system/lib/vndk-sp-28/libc++.so (std::__1::ios_base::Init::Init()+23)
11-15 10:39:42.340  4594  4594 E malloc_debug:           #08  pc 0003274a  /system/lib/vndk-sp-28/libc++.so

addr2line -ife out/target/product/xxxx/symbols/vendor/lib/libtest.so 00000c76
_Z6doTestv
vendor/xxx/common/system/libtest/testlib.cpp:14

 14     ALOGD("test begin1");
 15     void *p = malloc(sizeof(char) * 10);
①指出的是那块内存没有被释放。
②malloc_debug是在程序运行结束之后才打印出来。

替换library就不用重启了


3.结合heapsnap debug native内存泄漏
malloc debug只有当native进程退出的时候才能检测出来是不是有泄漏,但是怎么个退出法也没说,kill -9肯定是不行的。
验证发现github上面的heapsnap可以满足这方面的需求, 使用的是LD_PRELOAD加载动态库libheapsnap.so方式
和read.me上有差异,因为照搬的话有问题。
heapsnap地址

https://github.com/albuer/heapsnap
①准备工作,将编译的libheap.so push到vendor/lib,确保和二进制文件如vendor/bin/test在同一namespace
adb push libheapsnap.so vendor/lib/libheapsnap.so
adb shell chmod 0644 /data/local/tmp/libheapsnap.so
adb shell mkdir -p /data/local/tmp/heap_snap
adb shell chmod 0777 /data/local/tmp/heap_snap
②开启malloc debug调试
setprop libc.debug.malloc.options backtrace
setprop libc.debug.malloc.program vendor/bin/test
③配置LD_PRELOAD环境变量
export LD_PRELOAD=vendor/lib/libheapsnap.so
④执行目标进程
stop vendor/bin/test
vendor/bin/test
⑤通过signal 21获取目标进程的heap信息,并自动保存文件到/data/local/tmp/heap_snap/目录下
kill -21
⑥分析proc_3968_0000.heap,反编译等。
通过占有的内存大小排序和对应的栈,可以直接拿到对应的嫌疑代码行,从而定位问题。
Heap Snapshot v0.2

Total memory: 1167480
Allocation records: 8

size     4096, dup  285, 0xafd8bd4a, 0xaff98f54, 0x8b344ba2
          #00  pc 00000d4a  /vendor/lib/libtest.so (doTest()+85)
          #01  pc 00088f54  /system/lib/libc.so (__libc_init+47)
          #02  pc 00000ba2  /vendor/bin/test
size       48, dup    1, 0xafe98b66, 0xafe9c55e, 0xafe9caba, 0xafe9d40e
          #00  pc 00009b66  /system/lib/vndk-sp-28/libutils.so (android::SharedBuffer::alloc(unsigned int)+13)
          #01  pc 0000d55e  /system/lib/vndk-sp-28/libutils.so (android::VectorImpl::_grow(unsigned int, unsigned int)+285)
          #02  pc 0000daba  /system/lib/vndk-sp-28/libutils.so (android::VectorImpl::add(void const*)+13)
          #03  pc 0000e40e  /system/lib/vndk-sp-28/libutils.so (android::add_sysprop_change_callback(void (*)(), int)+93)

你可能感兴趣的:(Android malloc debug定位native内存问题(主要是内存泄漏))