与内存有关的问题可以分成两类:内存访问错误和内存使用错误。内存访问错误包括错误地读取内存和错误地写内存。错误地读取内存可能让你的模块返回意想不到的结果,从而导致后续的模块运行异常。错误地写内存可能导致系统崩溃。内存使用方面的错误主要是指申请的内存没有正确释放,从而使程序运行逐渐减慢,直至停止。
首先必须搞懂什么是内存泄漏,其实,业界一直有两种定义:
a. 大众化说法:一块内存由new或者malloc分配了,在程序结束前一直没有被回收。但程序始终有指针指向这块内存。
b. 更严格的说法:一块内存由new或者malloc分配在堆上面,在程序结束前,已经没有任何指针能够指向这块内存了。
对于第一种Memory Leak,其实危害不大,因为一旦进程结束了,所有该进程分配的内存(包括Leak掉的内存)都会被kernel回收。
对于第二种Memory Leak,大家一致认为对大型服务器端运行的程序是有危害的。如果程序一直在执行,Leak的内存会越来越多,可能会耗尽程序的堆内存。
相应的,在Valgrind里面,称第一种Leak为“still reachable”,称第二种为“memory leak”。对于memory leak又分为两种。Directly lost和Indirectly lost。
Memcheck
l
l
l
l
l
l
l
#include <</span>string.h>
void **rrr;
int main(void)
{
}
用Valgrind检查上面的代码:
$ valgrind --leak-check=full --show-reachable=yes ./a.out
==16420== 4 bytes in 1 blocks are indirectly lost in loss record 1 of 2
==16420== at 0x4A05E1C: malloc (vg_replace_malloc.c:195)
==16420== by 0x374EA79771: strdup (in /lib64/libc-2.5.so)
==16420== by 0x4005E2: main (in /home/zzhan17/test/a.out)
==16420==
==16420== 12 (8 direct, 4 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==16420== at 0x4A05E1C: malloc (vg_replace_malloc.c:195)
==16420== by 0x4005CA: main (in /home/zzhan17/test/a.out)
==16420==
==16420== LEAK SUMMARY:
==16420== definitely lost: 8 bytes in 1 blocks
==16420== indirectly lost: 4 bytes in 1 blocks
==16420== possibly lost: 0 bytes in 0 blocks
==16420== still reachable: 0 bytes in 0 blocks
==16420== suppressed: 0 bytes in 0 blocks
如果把上面的“rrr = NULL; ”代码删除, Valgrind不会报告任何memory leak但会显示有memory still reachable,原因是void **rrr是global pointer,程序退出时rrr还能指向AAA和BBB。