valgrind包含重量级的内存检查器memcheck。用于检查C和C++代码。能够发现:使用未初始化的内存,内存访问越界,内存泄露,使用已经释放了的内存等。使用memcheck会导致10%到30%的性能损失。
Memcheck侦听(intercept)分配和释放内存的函数调用,从而感知程序的内存使用情况。分配内存的函数有malloc、calloc、realloc、valloc、memalign、new,释放内存的函数有free和delete。
虽然memcheck不能检测出所有的内存错误。比如栈上静态分配内存的数组,访问越界时检测不到。但是它可以发现很多会导致程序崩溃的错误,比如segmentation fault。
使用方法:
编译程序时建议使用-g选项,这样才可以在错误消息中可以看到代码行号。
Valgrind调用方法:
valgrind [valgrind-options] your-prog [your-prog-options]
例如
valgrind --leak-check=full ./heap_overrun
选项--show-leak-kinds=
Memcheck报错含义:
1、Illegal read / Illegal write errors:比如读写还没有分配的内存块、读写已经被free的内存块、内存访问越界(包括超出堆中内存块的范围、访问了栈中不能访问的区域)。使用选项--read-var-info,虽然Memcheck会运行的更慢,但是可以给出更详细的信息。
2、Use of uninitialised values:使用未初始化的值,也就是说值不确定。有两种未初始化的成因:函数中的局部变量没有被初始化;堆上的内存块,在使用之前没有被初始化。如果想知道成因,使用选项--track-origins=yes。这虽然导致memcheck速度更慢,但是可以让定位出根本原因变得容易。
3、Use of uninitialised or unaddressable values in system calls。系统调用中参数是否已经初始化;如果要读程序提供的buffer,会检查buffer是否addressable、并且初始化了的;如果要写程序提供的buffer,会检查buffer是否addressable。后两点简单来说就是检查程序提供的buffer是否可用。
4、Illegal frees:重复释放内存块,或者指针没有指向内存的起始位置。
5、When a heap block is freed with an inappropriate deallocation function:C++专用报错,释放内存的函数没有和分配内存的函数相对应。下面是C++的内存分配和释放函数的配对要求:
1.如果使用malloc、calloc、realloc、valloc或者memalign分配内存,则只能使用free来释放内存。
2.如果使用new来分配内存,则只能使用delete来释放内存。
3.如果使用new[]分配内存,则只能使用delete[]来释放内存。
6、Overlapping source and destination blocks:用于检查memcpy、strcpy、strncpy、strcat、strncat的源和目的内存块是否有重叠。如果这些函数的source block和destination block有重叠,结果可能不正确。
7、Fishy argument values:需要的内存大小是负数或者大的离谱的正数。
8、Memory leak detection内存泄露报错:
Definitely lost:确定的内存泄露,程序已经无法访问这块内存了。它只是指出哪里分配的内存没有被释放,但是这个内存需要在哪里释放,要理解了程序才能知道。一块内存可能在很多执行路径中被使用,代码中,释放的位置可能有多处,任何一处没有释放都会导致泄露。所以修复bug可能并不容易。
Possibly lost:可能的内存泄露,仍然存在某个指针能够访问这块内存,但该指针指向的已经不是该内存块的起始位置。如果程序还能够找到内存块的起始位置,比如记录了当前指针相对于起始位置的偏移量,那么内存就还可以被释放。但是程序是否能够找到内存的起始位置,valgrind感知不到,这需要理解了程序的逻辑才能清楚。
Indirectly lost: 指向该内存的指针都位于已经泄露的内存中。
Still reachable:内存仍然可达。但是到程序结束时仍然没有释放。如果程序继续运行,也有可能会释放。缺省不报告。除非--show-reachable=yes。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)