写在前面:
本人只是一个linux开发新手,对linux下开发充满热情,前段时间接手一个linux下程序性能优化的工作,自己在整个过程中零零散散的总结了一些经验,特别把查找和定位内存泄漏方面的经验写下来,尤其是使用的几个开源工具,希望对别人有用,也等于自己做做笔记,便于以后再次使用或学习。
整个过程主要有以下几个方面:
1、阅读源代码及分析动态内存的使用
由于之前没有做过类似的问题(纯属小白了,惨遭鄙视....),所以就想着通过自己去看代码,查找里面涉及到使用动态内存的代码段去定位问题(现在想想,真是太幼稚了,大家见笑了...),但是自己还是去通过对源代码跟踪、分析,主要是对动态分配的内存(如malloc函数分配的内存)、一些文件描述符等进行跟踪,分析在程序逻辑中对动态分配的内存有没有手动进行释放,打开的文件描述符有没有关闭等这些代码一点点的去分析,当然这也是熟悉代码,了解的一个过程。
2、利用memwatch内存检测工具对程序进行内存分析
Memwatch是一款C语言的内存检测工具。memwatch使用它自己定义的功能函数取代所有在你的程序中用ANSI C定义的内存分配函数,memwatch的内存分配函数包含了所有的分配记录信息。memwatch功能默认不是开启的,除非定义了MEMWATCH,否则在代码中不会跟踪相关的内存使用情况。memwatch通常将它的数据写入到memwatch.log文件中,它也可以被重定向。
工具使用方法:
(1) 下载memwatch源码(http://www.linkdata.se/sourcecode.html)
(2) 将memwatch.c和memwatch.h文件拷贝到自己的工程目录中,并在工程中的每个.c文件中添加memwatch.h头文件
(3) 利用gun工具链编译时带上选项-DMEMWATCH及-DMW_STDIO,并将memwatch.c一并编译。例如工程文件为test.c,需要对其进行内存检测时可以如下进行编译:
gcc -o -DMEMWATCH -DMW_STDIOtest.c memwatch.c
(4) 运行编译好的可执行程序,有关内存使用信息日志文件就会保存在memwatch.log中。
优点:memwatch使用简单方便,工具本身占用内存少。
缺点:功能简单,不能检测出所有程序中存在的内存问题,可能会有遗漏。在我实践过程中,使用memwatch就不能检测出程序调用开源库函数时发生内存泄漏的问题,memwatch只能做简单的内存检测。
3、利用valgrind内存检测工具分析内存
Valgrind是运行在Linux上的一套基于仿真技术的程序调试和分析工具,它包含一个内核,一个软件合成的CPU,和一系列的小工具,每个工具都可以完成一项任务──调试,分析,或测试等。Valgrind可以检测内存泄漏和内存违例,还可以分析cache的使用等,灵活轻巧而又强大。
Valgrind一般包含下列工具:
(1) memcheck
最常用的工具,用来检测程序中出现的内存问题,所有对内存的读写都会被检测到,一切对malloc()/free()/new/delete的调用都会被捕获。所以,它能检测以下问题:
a.对未初始化内存的使用;
b.读/写释放后的内存块;
c.读/写超出malloc分配的内存块;
d.读/写不适当的栈中内存块;
e.内存泄漏,指向一块内存的指针永远丢失;
f.不正确的malloc/free或new/delete匹配;
g,memcpy()相关函数中的dst和src指针重叠。
这些问题往往是C/C++程序员最头疼的问题,Memcheck在这里帮上了大忙。
(2) Callgrind
和gprof类似的分析工具,但它对程序的运行观察更是入微,能给我们提供更多的信息。
(3) Cachegrind
Cache分析器,它模拟CPU中的一级缓存I1,Dl和二级缓存,能够精确地指出程序中cache的丢失和命中。
(4) Helgrind
它主要用来检查多线程程序中出现的竞争问题。Helgrind寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。
(5) Massif
堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。
Valgrind工具使用方法:
(1) 下载Valgrind源码(http://www.valgrind.org/)
(2) 按照工具要求安装Valgrind工具
(3) 待工具安装完成后,使用valgrind来运行程序即可,举例如下:
如编译好的工程文件为memleak,则使用valgrind运行memleak如下:
valgrind [options] ./memleak
通常使用到的选项有:--tool=memcheck (指定工具)
--leak-check=full(设置检测所有内存问题)
--show-leak-kinds=all(设置提示所有内存泄漏问题)
--track-origins=yes
--log-file=valgrind.log(设置检测的日志信息文本)
--track-fds=yes(设置检测文件描述符)
--time-stamp=yes(设置在日志文件中加入时间戳)
valgrind结果分析:内存泄露. Memcheck将内存泄露分为两种,一种是可能的内存泄露(Possibly lost),另外一种是确定的内存泄露(Definitely lost)。Possibly lost 是指仍然存在某个指针能够访问某块内存,但该指针指向的已经不是该内存首地址。Definitely lost 是指已经不能够访问这块内存。而Definitely lost又分为两种:直接的(direct)和间接的(indirect)。直接和间接的区别就是,直接是没有任何指针指向该内存,间接是指指向该内存的 指针都位于内存泄露处。
举例如下:
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all--log-file=valgrind.log --time-stamp=yes ./memleak
优点:功能强力,使用灵活,较memwatch工具全面,可以检测出各种内存问题。
缺点:使用复杂一些,需要安装,使用时会占用较大的内存。
以上就先把总结写一下,之后再慢慢将检测的结果做一个事例贴代码出来!感谢大家关注!