memleax是个开源项目,原理是通过注入hook目标进程的malloc(new也是用的malloc)内存分配函数,在指定时间未释放则认为内存泄漏。优点是不需要重启,attach到目标进程。
github地址:http://wubingzheng.github.io/memleax/
ubuntu编译需要安装 libunwind8-dev、libelf-dev 和 libdw-dev 3个库。
测试代码:
#include <iostream> #include <unistd.h> #include <fstream> using namespace std; int main() { while (1) { cout << "Hello world" << endl; cout << "Hello world" << endl; cout << "Hello world" << endl; cout << "Hello world" << endl; cout << "Hello world" << endl; ofstream myfile; myfile.open ("1.txt"); cout << "Hello world" << endl; cout << "Hello world" << endl; cout << "Hello world" << endl; cout << "Hello world" << endl; cout << "Hello world" << endl; cout << "Hello world" << endl; cout << "Hello world" << endl; char *p = new char(100); usleep(3000 * 1000); } }
$ sudo memleax -e 2 2972 == Begin monitoring process 2972... CallStack[1]: memory expires with 552 bytes, backtrace: 0x00007f07e2a8e4a0 libc-2.21.so __libc_malloc()+0 /build/buildd/glibc-2.21/libio/genops.c:1320 0x00007f07e2a7911d libc-2.21.so ?() /build/buildd/glibc-2.21/libio/iofopen.c:69 0x00007f07e3067120 libstdc++.so _ZNSt12__basic_fileIcE4openEPKcSt13_Ios_Openmo()+48 0x00007f07e30a918a libstdc++.so _ZNSt13basic_filebufIcSt11char_traitsIcEE4open()+74 0x00007f07e30a93e0 libstdc++.so _ZNSt14basic_ofstreamIcSt11char_traitsIcEE4ope()+16 0x0000000000400c31 cppleak main()+219 /home/kiiim/aosp/memleak_test/1.cpp:19 CallStack[2]: memory expires with 8192 bytes, backtrace: 0x00007f07e2a8e4a0 libc-2.21.so __libc_malloc()+0 /build/buildd/glibc-2.21/libio/genops.c:1320 0x00007f07e3049698 libstdc++.so _Znwm()+24 0x00007f07e3049749 libstdc++.so _Znam()+9 0x00007f07e30a9231 libstdc++.so _ZNSt13basic_filebufIcSt11char_traitsIcEE4open()+241 0x00007f07e30a93e0 libstdc++.so _ZNSt14basic_ofstreamIcSt11char_traitsIcEE4ope()+16 0x0000000000400c31 cppleak main()+219 /home/kiiim/aosp/memleak_test/1.cpp:19 CallStack[3]: memory expires with 1 bytes, backtrace: 0x00007f07e2a8e4a0 libc-2.21.so __libc_malloc()+0 /build/buildd/glibc-2.21/libio/genops.c:1320 0x00007f07e3049698 libstdc++.so _Znwm()+24 0x0000000000400cff cppleak main()+425 /home/kiiim/aosp/memleak_test/1.cpp:28 CallStack[2]: expired-memory frees after 3 seconds CallStack[1]: expired-memory frees after 3 seconds CallStack[1]: memory expires with 552 bytes, 2 times again CallStack[2]: memory expires with 8192 bytes, 2 times again CallStack[3]: memory expires with 1 bytes, 2 times again CallStack[2]: expired-memory frees after 3 seconds CallStack[1]: expired-memory frees after 3 seconds CallStack[1]: memory expires with 552 bytes, 3 times again CallStack[2]: memory expires with 8192 bytes, 3 times again CallStack[3]: memory expires with 1 bytes, 3 times again CallStack[2]: expired-memory frees after 3 seconds Warning: too many expired-free at CallStack[2]. will not show this CallStack later CallStack[1]: expired-memory frees after 3 seconds Warning: too many expired-free at CallStack[1]. will not show this CallStack later CallStack[3]: memory expires with 1 bytes, 4 times again CallStack[3]: memory expires with 1 bytes, 5 times again CallStack[3]: memory expires with 1 bytes, 6 times again CallStack[3]: memory expires with 1 bytes, 7 times again CallStack[3]: memory expires with 1 bytes, 8 times again CallStack[3]: memory expires with 1 bytes, 9 times again CallStack[3]: memory expires with 1 bytes, backtrace: 0x00007f07e2a8e4a0 libc-2.21.so __libc_malloc()+0 /build/buildd/glibc-2.21/libio/genops.c:1320 0x00007f07e3049698 libstdc++.so _Znwm()+24 0x0000000000400cff cppleak main()+425 /home/kiiim/aosp/memleak_test/1.cpp:28
标志 char *p = new char(100); 的内存泄漏。
CallStack[2]: memory expires with 8192 bytes, 3 times again
CallStack[2]:expired-memory frees after 3 seconds Warning: too many expired-free at CallStack[2]. will not show this CallStack later
文件句柄因为在while结束时会释放,程序很人性化。屏蔽了这个告警。