一、valgrind基础知识介绍
Valgrind通常用来成分析程序性能及程序中的内存泄露错误。
1、 Valgrind工具集简绍
Valgrind包含下列工具:
1、memcheck:检查程序中的内存问题,如泄漏、越界、非法指针等。
2、callgrind:检测程序代码的运行时间和调用过程,以及分析程序性能。
3、cachegrind:分析CPU的cache命中率、丢失率,用于进行代码优化。
4、helgrind:用于检查多线程程序的竞态条件。
5、massif:堆栈分析器,指示程序中使用了多少堆内存等信息。
6、lackey:
7、nulgrind:
这几个工具的使用是通过命令:valgrind --tool=name 程序名来分别调用的,当不指定tool参数时默认是 --tool=memcheck
如果要检查内存泄漏,只需要增加--leak-check=yes就可以了,命令如下:
valgrind --tool=memcheck --leak-check=yes ./文件名 #这个是全写
valgrind --leak-check=yes ./文件名 #可以简写如下
不同工具间加入的代码变化非常的大。在每个作用域的末尾,memcheck加入代码检查每一片内存的访问和进行值计算,代码大小至少增加12倍,运行速度要比平时慢25到50倍。valgrind模拟程序中的每一条指令执行,因此,检查工具和剖析工具不仅仅是对你的应用程序,还有对共享库,GNU C库,X的客户端库都起作用。
2、 Valgrind工具详解
(1)Memcheck
最常用的工具,用来检测程序中出现的内存问题,所有对内存的读写都会被检测到,一切对malloc、free、new、delete的调用都会被捕获。所以,它能检测以下问题:
1、对未初始化内存的使用;
2、读/写释放后的内存块;
3、读/写超出malloc分配的内存块;
4、读/写不适当的栈中内存块;
5、内存泄漏,指向一块内存的指针永远丢失;
6、不正确的malloc/free或new/delete匹配;
7、memcpy()相关函数中的dst和src指针重叠。
这些问题往往是C/C++程序员最头疼的问题,Memcheck能在这里帮上大忙。
二、valgrind的安装:
第一步:获取Valgrind 包 可以先使用浏览器访问http://valgrind.org/downloads/查看当前版本。valgrind-3.11.0.tar.bz2
wget http://valgrind.org/downloads/valgrind-3.11.0.tar.bz2
我是直接在windows下载下来然后rz到centos虚拟机的。
第二步:将下载的文件解压
tar -jxvf valgrind-3.11.0.tar.bz2
第三步:安装和配置
./autogen.sh
./configure
make
make install
注意1:执行./autogen.sh的时候可能存在如下报错。
原因与解决:丢失的aclocal是automake包的一部分,因此,要修复该错误,请安装以下包。
sudo yum install automake
(2)在Debian,Ubuntu或Linux Mint上:
sudo apt-get install automake
注意2:我在两个虚拟机下都进了测试。安装当前最新版本valgrind-3.13.0.tar.bz2每次检测到的error都是0,也就是说检测不到错误。卸载后换成valgrind-3.11.0.tar.bz2才可以正常的检测到内存泄漏!!卸载方法
三、valgrind的使用
实例一:
1、首先建立如下a.c文件(存在一个内存泄漏和一个内存错误)。
#include <stdlib.h>
void f(void)
{
int*x = (int *)malloc(10 * sizeof(int));
x[10]= 0;
//problem 1: heap block overrun
} //problem 2: memory leak -- x not freed
int main(void)
{
f();
return 0;
}
2、执行如下指令
gcc -g a.c -o a #先编译
valgrind --leak-check=yes ./a #再检查
3、执行结果如下:
[root@init1 testfile]# valgrind --leak-check=yes ./a
==29936== Memcheck, a memory error detector
==29936== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==29936== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==29936== Command: ./a
==29936==
==29936== Invalid write of size 4
==29936== at 0x40054E: f (a.c:5)
==29936== by 0x40055E: main (a.c:10)
==29936== Address 0x5203068 is 0 bytes after a block of size 40 alloc'd
==29936== at 0x4C29C3D: malloc (vg_replace_malloc.c:299)
==29936== by 0x400541: f (a.c:4)
==29936== by 0x40055E: main (a.c:10)
==29936==
==29936==
==29936== HEAP SUMMARY:
==29936== in use at exit: 40 bytes in 1 blocks
==29936== total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==29936==
==29936== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==29936== at 0x4C29C3D: malloc (vg_replace_malloc.c:299)
==29936== by 0x400541: f (a.c:4)
==29936== by 0x40055E: main (a.c:10)
==29936==
==29936== LEAK SUMMARY:
==29936== definitely lost: 40 bytes in 1 blocks
==29936== indirectly lost: 0 bytes in 0 blocks
==29936== possibly lost: 0 bytes in 0 blocks
==29936== still reachable: 0 bytes in 0 blocks
==29936== suppressed: 0 bytes in 0 blocks
==29936==
==29936== For counts of detected and suppressed errors, rerun with: -v
==29936== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 6)
实例二:
1、建立如下file5.文件
#include <string.h>
int main(int argc, char *argv[])
{
char *ptr;
ptr = (char*) malloc(10);
strcpy(ptr, "01234567890");
return 0;
}
2、执行如下指令
gcc -g file5.c -o file5 #先编译
valgrind --leak-check=yes ./file5 #再检查
3、结果如下:
[root@init1 testfile]# valgrind --leak-check=yes ./file5
==29976== Memcheck, a memory error detector
==29976== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==29976== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==29976== Command: ./file5
==29976==
==29976== Invalid write of size 4
==29976== at 0x40055E: main (file5.c:7)
==29976== Address 0x5203048 is 8 bytes inside a block of size 10 alloc'd
==29976== at 0x4C29C3D: malloc (vg_replace_malloc.c:299)
==29976== by 0x400548: main (file5.c:6)
==29976==
==29976==
==29976== HEAP SUMMARY:
==29976== in use at exit: 10 bytes in 1 blocks
==29976== total heap usage: 1 allocs, 0 frees, 10 bytes allocated
==29976==
==29976== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==29976== at 0x4C29C3D: malloc (vg_replace_malloc.c:299)
==29976== by 0x400548: main (file5.c:6)
==29976==
==29976== LEAK SUMMARY:
==29976== definitely lost: 10 bytes in 1 blocks
==29976== indirectly lost: 0 bytes in 0 blocks
==29976== possibly lost: 0 bytes in 0 blocks
==29976== still reachable: 0 bytes in 0 blocks
==29976== suppressed: 0 bytes in 0 blocks
==29976==
==29976== For counts of detected and suppressed errors, rerun with: -v
==29976== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 6)
实例三:
1、建立如下file2.c文件
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
void test() {
int *ptr = malloc(sizeof(int)*10);
ptr[10] = 7; // 内存越界
memcpy(ptr +1, ptr, 5); // 踩内存
free(ptr);
free(ptr);// 重复释放
int *p1;
*p1 = 1; // 非法指针
}
int main(void)
{
test();
return 0;
}
2、执行如下指令:
gcc -g file2.c -o file2
valgrind --leak-check=yes ./file2
3、结果如下:
[root@init1 testfile]# valgrind --leak-check=yes ./file2
==29992== Memcheck, a memory error detector
==29992== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==29992== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==29992== Command: ./file2
==29992==
==29992== Invalid write of size 4
==29992== at 0x4005FE: test (file2.c:6)
==29992== by 0x400651: main (file2.c:16)
==29992== Address 0x5203068 is 0 bytes after a block of size 40 alloc'd
==29992== at 0x4C29C3D: malloc (vg_replace_malloc.c:299)
==29992== by 0x4005F1: test (file2.c:5)
==29992== by 0x400651: main (file2.c:16)
==29992==
==29992== Source and destination overlap in memcpy(0x5203044, 0x5203040, 5)
==29992== at 0x4C2E21C: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1018)
==29992== by 0x40061F: test (file2.c:7)
==29992== by 0x400651: main (file2.c:16)
==29992==
==29992== Invalid free() / delete / delete[] / realloc()
==29992== at 0x4C2AD57: free (vg_replace_malloc.c:530)
==29992== by 0x400637: test (file2.c:9)
==29992== by 0x400651: main (file2.c:16)
==29992== Address 0x5203040 is 0 bytes inside a block of size 40 free'd
==29992== at 0x4C2AD57: free (vg_replace_malloc.c:530)
==29992== by 0x40062B: test (file2.c:8)
==29992== by 0x400651: main (file2.c:16)
==29992== Block was alloc'd at
==29992== at 0x4C29C3D: malloc (vg_replace_malloc.c:299)
==29992== by 0x4005F1: test (file2.c:5)
==29992== by 0x400651: main (file2.c:16)
==29992==
==29992== Use of uninitialised value of size 8
==29992== at 0x40063C: test (file2.c:11)
==29992== by 0x400651: main (file2.c:16)
==29992==
==29992==
==29992== Process terminating with default action of signal 11 (SIGSEGV)
==29992== Bad permissions for mapped region at address 0x400660
==29992== at 0x40063C: test (file2.c:11)
==29992== by 0x400651: main (file2.c:16)
==29992==
==29992== HEAP SUMMARY:
==29992== in use at exit: 0 bytes in 0 blocks
==29992== total heap usage: 1 allocs, 2 frees, 40 bytes allocated
==29992==
==29992== All heap blocks were freed -- no leaks are possible
==29992==
==29992== For counts of detected and suppressed errors, rerun with: -v
==29992== Use --track-origins=yes to see where uninitialised values come from
==29992== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 6 from 6)
段错误(吐核)