内存泄漏是指由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。
我们平时开发过程中不可避免的会遇到内存泄漏问题,你是如何排查的呢?估计你是使用下面这几个工具吧?valgrind
mtrace
dmalloc
ccmalloc
memwatch
debug_new
这里程序喵向大家推荐新的一个排查内存泄漏的工具:AddressSanitizer(ASan),该工具为gcc自带,4.8以上版本都可以使用,支持Linux、OS、Android等多种平台,不止可以检测内存泄漏,它其实是一个内存错误检测工具,可以检测的问题有:内存泄漏
堆栈和全局内存越界访问
free后继续使用
局部内存被外层使用
Initialization order bugs(中文不知道怎么翻译才好,后面有代码举例,重要)
使用方法直接看我下面的代码:
检测内存泄漏
内存泄漏代码:#include void func1(){ malloc(7); }void func2(){ malloc(5); }int main(){func1();func2();return 0;}
编译and输出:g++ -fsanitize=address -g test_leak.cc && ./a.out===================================================================103==ERROR: LeakSanitizer: detected memory leaksDirect leak of 7 byte(s) in 1 object(s) allocated from:#0 0x7f95b231eb40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40)#1 0x7f95b36007f7 in func1() /home/wangzhiqiang/test/test_leak.cc:3#2 0x7f95b3600814 in main /home/wangzhiqiang/test/test_leak.cc:8#3 0x7f95b1e61b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)Direct leak of 5 byte(s) in 1 object(s) allocated from:#0 0x7f95b231eb40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40)#1 0x7f95b3600808 in func2() /home/wangzhiqiang/test/test_leak.cc:5#2 0x7f95b3600819 in main /home/wangzhiqiang/test/test_leak.cc:9#3 0x7f95b1e61b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)SUMMARY: AddressSanitizer: 12 byte(s) leaked in 2 allocation(s).
编译方式很简单,只需要添加-fsanitize=address -g就可以检测出具体产生内存泄漏的位置以及泄漏空间的大小。
检测堆栈内存越界访问
示例:#include int main(){int *array = new int[100];array[0] = 0;int res = array[100]; // out of boundsdelete[] array;return res;}
编译and输出:g++ -fsanitize=address -g test_leak.cc && ./a.out===================================================================110==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6140000001d0 at pc 0x7f0e06400d2e bp 0x7ffff5963f10 sp 0x7ffff5963f00READ of size 4 at 0x6140000001d0 thread T0#0 0x7f0e06400d2d in main /home/wangzhiqiang/test/test_leak.cc:6#1 0x7f0e048d1b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)#2 0x7f0e06400bb9 in _start (/mnt/d/wzq/wzq/util/test/a.out+0xbb9)0x6140000001d0 is located 0 bytes to the right of 400-byte region [0x614000000040,0x6140000001d0)allocated by thread T0 here:#0 0x7f0e05120608 in operator new[](unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xe0608)#1 0x7f0e06400cab in main /home