如何使用Valgrind memcheck工具进行C/C++的内存泄漏检测

系统编程中一个重要的方面就是有效地处理与内存相关的问题。你的工作越接近系统,你就需要面对越多的内存问题。有时这些问题非常琐碎,而更多时候它会演变成一个调试内存问题的恶梦。所以,在实践中会用到很多工具来调试内存问题。


Valgrind是运行在Linux上一套基于仿真技术的程序调试和分析工具,它包含一个内核——一个软件合成的CPU,和一系列的小工具,每个工具都可以完成一项任务──调试,分析,或测试等。Valgrind可以检测内存泄漏和内存违例,还可以分析cache的使用等,灵活轻巧而又强大,能直穿程序错误的心脏,真可谓是程序员的瑞士军刀。


Valgrind工具包包含多个工具:

  • Memcheck是一个内存错误检测器。它有助于使你的程序,尤其是那些用C和C++写的程序,更加准确。
  • Cachegrind是一个缓存和分支预测分析器。它有助于使你的程序运行更快。
  • Callgrind是一个调用图缓存生成分析器。它与Cachegrind的功能有重叠,但也收集Cachegrind不收集的一些信息
  • Helgrind是一个线程错误检测器。它有助于使你的多线程程序更加准确。
  • DRD也是一个线程错误检测器。它和Helgrind相似,但使用不同的分析技术,所以可能找到不同的问题。
  • Massif是一个堆分析器。它有助于使你的程序使用更少的内存。
  • DHAT是另一种不同的堆分析器。它有助于理解块的生命期、块的使用和布局的低效等问题。
  • SGcheck是一个实验工具,用来检测堆和全局数组的溢出。它的功能和Memcheck互补:SGcheck找到Memcheck无法找到的问题,反之亦然。
  • BBV是个实验性质的SimPoint基本块矢量生成器。它对于进行计算机架构的研究和开发很有用处。

这里给大家介绍如何使用Valgrind memcheck工具进行C/C++的内存泄漏检测。memcheck工具主要检查下面的程序错误:

  • 使用未初始化的内存 (Use of uninitialised memory)
  • 使用已经释放了的内存 (Reading/writingmemory after it has been free’d)
  • 使用超过 malloc分配的内存空间(Reading/writing off the end of malloc’d blocks)
  • 对堆栈的非法访问 (Reading/writinginappropriate areas on the stack)
  • 申请的空间是否有释放 (Memory leaks –where pointers to malloc’d blocks are lost forever)
  • malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
  • src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions)

这几个工具的使用是通过命令:valgrind --tool=name 程序名来分别调用的,当不指定tool参数时默认是 --tool=memcheck 。


使用前,需要保证valgrind已经安装:


如果是ubuntu系统,在线安装即可:



使用 valgrind memcheck 方式:

  • 编译代码时,加上调试参数 -g (用来在memcheck的输出中生成行号,如果出现错误,可以定位到错误出现的位置)
  • --leak-check=full 指的是完全检查内存泄漏
  • a.out 为需要检查的可执行程序,有些系统(如ubuntu),如果加上“./”:


1. 使用未初始化的内存

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.    
  4. int main(void)  
  5. {  
  6.     char *p;  
  7.    
  8.     char c = *p;  //使用未初始化的内存  
  9.    
  10.     printf("\n [%c]\n",c);  
  11.    
  12.     return 0;  
  13. }  

在上面的代码中,我们尝试使用未初始化的指针“p”,让我们运行 Memcheck 来检查结果:


2. 在内存被释放后进行读/写

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.    
  4. int main(void)  
  5. {  
  6.     char *p = malloc(1);  
  7.     *p = 'a';  
  8.    
  9.     char c = *p;  
  10.    
  11.     printf("\n [%c]\n",c);  
  12.    
  13.     free(p);  
  14.     c = *p;//在内存被释放后进行读/写  
  15.       
  16.     return 0;  
  17. }  

调试结果如下:


3. 从已分配内存块的尾部进行读/写

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.    
  4. int main(void)  
  5. {  
  6.     char *p = malloc(1);  
  7.     *p = 'a';  
  8.    
  9.     char c = *(p+1); //从已分配内存块的尾部进行读/写  
  10.    
  11.     printf("\n [%c]\n",c);  
  12.    
  13.     free(p);  
  14.     return 0;  
  15. }  

调试结果如下:


4. 内存泄露

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. //在这次的代码中, 我们申请了一个字节但是没有将它释放  
  5. int main(void)  
  6. {  
  7.     char *p = malloc(1);  
  8.     *p = 'a';  
  9.    
  10.     char c = *p;  
  11.    
  12.     printf("\n [%c]\n",c);  
  13.    
  14.     return 0;  
  15. }  

调试结果如下:


5. 不匹配地使用malloc/new/new[] 和 free/delete/delete[]

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include<iostream>  
  4.    
  5. int main(void)  
  6. {  
  7.     char *p = (char*)malloc(1);  
  8.     *p = 'a';  
  9.    
  10.     char c = *p;  
  11.    
  12.     printf("\n [%c]\n",c);  
  13.     delete p;  
  14.     return 0;  
  15. }  

上面的代码中,我们使用了malloc()来分配内存,但是使用了delete操作符来删除内存。

注意: 使用g++来编译上面的代码,因为delete操作符是在C++中引进的,而要编译C++需要使用g++。

调试结果如下:



6. 两次释放内存

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.    
  4. int main(void)  
  5. {  
  6.     char *p = (char*)malloc(1);  
  7.     *p = 'a';  
  8.    
  9.     char c = *p;  
  10.     printf("\n [%c]\n",c);  
  11.     free(p);  
  12.     free(p);  
  13.     return 0;  
  14. }  

调试结果如下:



本文转自:http://www.oschina.net/translate/valgrind-memcheck

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值