作者:gfree.wind@gmail.com
博客:blog.focus-linux.net   linuxfocus.blog.chinaunix.net 
 
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
======================================================================================================
 

欲善其事,必先利其器。Valgrind作为一个免费且优秀的工具包,平时大部分人可能都是使用valgrind检测内存问题,如内存泄露,越界等。其实
Valgrind的用途远不止于此,其实际上为一个工具包,除了检查内存问题以外,还有其它多项用途。我准备将其大致介绍一下。本不想再介绍
Valgrind检测内存问题的用法的,但是又一想,毕竟这是Valgrind的一个最有名的用途,如果少了它,不免有些遗憾,所以还是把检查内存问题作
为第一篇吧。
 
请看一下代码:
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. static void mem_leak1(void)
  5. {
  6. char *p = malloc(1);
  7. }
  8. static void mem_leak2(void)
  9. {
  10. FILE *fp = fopen("test.txt", "w");
  11. }
  12. static void mem_overrun1(void)
  13. {
  14. char *p = malloc(1);
  15. *(short*)p = 2;
  16. free(p);
  17. }
  18. static void mem_overrun2(void)
  19. {
  20. char array[5];
  21. strcpy(array, "hello");
  22. }
  23. static void mem_double_free(void)
  24. {
  25. char *p = malloc(1);
  26. free(p);
  27. free(p);
  28. }
  29. static void mem_use_wild_pointer(void)
  30. {
  31. char *p = (void*)0x80184800;
  32. *p = 1;
  33. }
  34. static void mem_free_wild_pointer(void)
  35. {
  36. char *p;
  37. free(p);
  38. }
  39. int main()
  40. {
  41. mem_leak1();
  42. mem_leak2();
  43. mem_overrun1();
  44. mem_overrun2();
  45. mem_double_free();
  46. //mem_use_wild_pointer();
  47. mem_free_wild_pointer();
  48. return 0;
  49. }

里一共列出了七种常见的内存问题:1. 动态内存泄露;2. 资源泄露,这里以文件描述符为例;3.
动态内存越界;4.数组内存越界;5.动态内存double
free;6.使用野指针,即未初始化的指针;7.释放野指针,即未初始化的指针;其中由于本示例代码过于简单,第6中情况,使用野指针会直接导致
crash,所以在main中,并没有真正的调用那个示例代码。由于valgrind只能检测执行到的代码,所以在后面的报告中,不会报告第6种错误情
况。但是,在大型的项目中,有可能使用野指针并不会导致程序crash。另外上面的7中情况,有些情况严格的说,实际上可以归为一类。
 
下面看怎样执行valgrind来检测内存错误:
  1. valgrind --track-fds=yes --leak-check=full --undef-value-errors=yes ./a.out
上面那些option的具体含义,可以参加valgrind --help,其中有些option默认就是打开的,不过我习惯于明确的使用option,以示清晰。
 
看执行后的报告:
  1. ==2326== Memcheck, a memory error detector
  2. ==2326== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
  3. ==2326== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
  4. ==2326== Command: ./a.out
  5. ==2326==
  6. /* 这里检测到了动态内存的越界,提示Invalid write。*/
  7. ==2326== Invalid write of size 2
  8. ==2326== at 0x80484B4: mem_overrun1 (in /home/fgao/works/test/a.out)
  9. ==2326== by 0x8048553: main (in /home/fgao/works/test/a.out)
  10. ==2326== Address 0x40211f0 is 0 bytes inside a block of size 1 alloc'd
  11. ==2326== at 0x4005BDC: malloc (vg_replace_malloc.c:195)
  12. ==2326== by 0x80484AD: mem_overrun1 (in /home/fgao/works/test/a.out)
  13. ==2326== by 0x8048553: main (in /home/fgao/works/test/a.out)
  14. ==2326==
 /* 这里检测到了double free问题,提示Invalid Free */
  1. ==2326== Invalid free() / delete / delete[]
  2. ==2326== at 0x40057F6: free (vg_replace_malloc.c:325)
  3. ==2326== by 0x8048514: mem_double_free (in /home/fgao/works/test/a.out)
  4. ==2326== by 0x804855D: main (in /home/fgao/works/test/a.out)
  5. ==2326== Address 0x4021228 is 0 bytes inside a block of size 1 free'd
  6. ==2326== at 0x40057F6: free (vg_replace_malloc.c:325)
  7. ==2326== by 0x8048509: mem_double_free (in /home/fgao/works/test/a.out)
  8. ==2326== by 0x804855D: main (in /home/fgao/works/test/a.out)
  9. ==2326==
  10. /* 这里检测到了未初始化变量 */
  11. ==2326== Conditional jump or move depends on uninitialised value(s)
  12. ==2326== at 0x40057B6: free (vg_replace_malloc.c:325)
  13. ==2326== by 0x804853C: mem_free_wild_pointer (in /home/fgao/works/test/a.out)
  14. ==2326== by 0x8048562: main (in /home/fgao/works/test/a.out)
  15. ==2326==
 /* 这里检测到了非法是否野指针 */
  1. ==2326== Invalid free() / delete / delete[]
  2. ==2326== at 0x40057F6: free (vg_replace_malloc.c:325)
  3. ==2326== by 0x804853C: mem_free_wild_pointer (in /home/fgao/works/test/a.out)
  4. ==2326== by 0x8048562: main (in /home/fgao/works/test/a.out)
  5. ==2326== Address 0x4021228 is 0 bytes inside a block of size 1 free'd
  6. ==2326== at 0x40057F6: free (vg_replace_malloc.c:325)
  7. ==2326== by 0x8048509: mem_double_free (in /home/fgao/works/test/a.out)
  8. ==2326== by 0x804855D: main (in /home/fgao/works/test/a.out)
  9. ==2326==
  10. ==2326==
  11. /*
  12. 这里检测到了文件指针资源的泄露,下面提示说有4个文件描述符在退出时仍是打开的。
  13. 描述符0,1,2无需关心,通过报告,可以发现程序中自己明确打开的文件描述符没有关闭。
  14. */
  15. ==2326== FILE DESCRIPTORS: 4 open at exit.
  16. ==2326== Open file descriptor 3: test.txt
  17. ==2326== at 0x68D613: __open_nocancel (in /lib/libc-2.12.so)
  18. ==2326== by 0x61F8EC: __fopen_internal (in /lib/libc-2.12.so)
  19. ==2326== by 0x61F94B: fopen@@GLIBC_2.1 (in /lib/libc-2.12.so)
  20. ==2326== by 0x8048496: mem_leak2 (in /home/fgao/works/test/a.out)
  21. ==2326== by 0x804854E: main (in /home/fgao/works/test/a.out)
  22. ==2326==
  23. ==2326== Open file descriptor 2: /dev/pts/4
  24. ==2326== <inherited from parent>
  25. ==2326==
  26. ==2326== Open file descriptor 1: /dev/pts/4
  27. ==2326== <inherited from parent>
  28. ==2326==
  29. ==2326== Open file descriptor 0: /dev/pts/4
  30. ==2326== <inherited from parent>
  31. ==2326==
  32. ==2326==
  33. /* 堆信息的总结:一共调用4次alloc,4次free。之所以正好相等,因为上面有一函数少了free,有一个函数多了一个free */
  34. ==2326== HEAP SUMMARY:
  35. ==2326== in use at exit: 353 bytes in 2 blocks
  36. ==2326== total heap usage: 4 allocs, 4 frees, 355 bytes allocated
  37. ==2326==
  38. /* 检测到一个字节的内存泄露 */
  39. ==2326== 1 bytes in 1 blocks are definitely lost in loss record 1 of 2
  40. ==2326== at 0x4005BDC: malloc (vg_replace_malloc.c:195)
  41. ==2326== by 0x8048475: mem_leak1 (in /home/fgao/works/test/a.out)
  42. ==2326== by 0x8048549: main (in /home/fgao/works/test/a.out)
  43. ==2326==
  44. /* 内存泄露的总结 */
  45. ==2326== LEAK SUMMARY:
  46. ==2326== definitely lost: 1 bytes in 1 blocks
  47. ==2326== indirectly lost: 0 bytes in 0 blocks
  48. ==2326== possibly lost: 0 bytes in 0 blocks
  49. ==2326== still reachable: 352 bytes in 1 blocks
  50. ==2326== suppressed: 0 bytes in 0 blocks
  51. ==2326== Reachable blocks (those to which a pointer was found) are not shown.
  52. ==2326== To see them, rerun with: --leak-check=full --show-reachable=yes
  53. ==2326==
  54. ==2326== For counts of detected and suppressed errors, rerun with: -v
  55. ==2326== Use --track-origins=yes to see where uninitialised values come from
  56. ==2326== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 12 from 8)
 

个只是一个简单的示例程序,即使没有Valgrind,我们也可以很轻易的发现问题。但是在真实的项目中,当代码量达到万行,十万行,甚至百万行时。由于
申请的内存可能不是在一个地方使用,不可避免的被传来传去。这时,如果光是看review代码来检查问题,可能很难找到根本原因。这时,使用
Valgrind则可以很容易的发现问题所在。
 
当然,Valgrind也不是万能的。我也遇到过Valgrind无法找到问题,反而我通过不断的review代码找到了症结。发现问题,解决问题,毕竟是末流。最好的方法,就是不引入内存问题。这可以通过良好的代码风格和设计来实现的。
 
写代码不是那么容易的。要用心,把代码当作自己的作品,真心的去写好它。这样,自然而然的就会把代码写好。
 
Note:这里我还要再次鄙视GFW,整个儿一个瞎搞!我连Valgrind的主站都打不开了。请问,Valgrind有什么敏感词!闭关锁国!难道让我成天的FQ!!!
 

Memory Leak
valgrind :
valgrind --tool=memcheck --leak-check=full <app> //检查内存泄漏、越界等错误
sample:
valgrind --tool=memcheck --leak-check=full ./bin/hostSample

转: 使用valgrind检查内存问题的更多相关文章

  1. 使用valgrind检查内存

    Valgrind是运行在Linux上一套基于仿真技术的程序调试和分析工具,是公认的最接近Purify的产品,它包含一个内核——一个软件合成的CPU,和一系列的小工具,每个工具都可以完成一项任务——调试 ...

  2. 用valgrind检查内存问题

    Valgrind Valgrind作为一个免费且优秀的工具包,平时大部分人可能都是使用valgrind检测内存问题,如内存泄露,越界等. Valgrind工具包包含多个工具,如Memcheck,Cac ...

  3. valgrind 检查内存泄露

    https://www.oschina.net/translate/valgrind-memcheck

  4. Linux 下用 valgrind 查找内存泄漏小例子

    1.安装 valgrind yum install valgrind 2.测试用例 main.cpp #include <iostream> using namespace std; st ...

  5. valgrind massif内存分析[转]

    valgrind检查内存泄露 #valgrind   ./程序 内存泄漏问题,我们有memcheck工具来检查.很爽.但是有时候memcheck工具查了没泄漏,程序一跑,内存还是狂飙.这又是什么问题. ...

  6. Valgrind检测内存泄露简介

    原文地址: Valgrind 概述 体系结构 Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合.Valgrind由内核(core)以及基于内核的其他调试工具组成.内核 ...

  7. Valgrind查找内存泄露利器

    Valgrind是一个GPL的软件,用于Linux(For x86, amd64 and ppc32)程序的内存调试和代码剖析.你可以在它的环境中运行你的程序来监视内存的使用情况,比如C 语言中的ma ...

  8. valgrind调查内存leak

    快有几个月没更新了,记录一下最近解决问题用到的工具吧. 最近代码跑压力测试,总是发现内存在无规律的慢慢增加,因此在Android上用上了大名顶顶的valgrind,说实话,真是名不虚传, 真是建议以后 ...

  9. 用mtrace检查内存泄漏

    http://blog.csdn.net/ixidof/article/details/6638066内存泄漏检查方法(for Linux) 如果你更想读原始文档, 请参考glibc info的&qu ...

随机推荐

  1. Android(java)学习笔记183:多媒体之图形颜色的变化

    1.相信大家都用过美图秀秀中如下的功能,调整颜色: 2. 下面通过案例说明Android中如何调色: 颜色矩阵 ColorMatrix cm = new ColorMatrix(); paint.se ...

  2. 在Eclipse中通过JDBC连接MySQL步骤,非常详细!

    通过JDBC连接MySQL基本步骤代码讲解步骤可能遇到的Bug基本步骤JDBC访问MySQL 1.加载JDBC驱动器—>哪个project需要,就添加到该project的jdbc文件夹下,我的j ...

  3. MyBatis基本运行环境

    MyBatis基本运行环境 1. 创建项目 2.拷贝jar加入到项目中build path jar包 3.创建数据库的表及数据添加 USE [mybatis] CREATE TABLE [dbo].[ ...

  4. JavaSE-30 BigDecimal类的使用

    问题 Java(其他编程语言也存在类似问题)中浮点数直接进行算术运算会导致精度丢失. 示例代码: System.out.println("1.0 - 0.9 =" + (1.0 - ...

  5. OpenCV2:总结篇 工具方法函数

    一.简介 OpenCV提供了一些工具方法函数来辅助完成图像运算 二.时间相关 1.getTickCount()和getTickFrequency() double tTime; tTime = (do ...

  6. FastDFS和集中存储方式对比

    指标 FastDFS   NFS  集中存储设备如NetApp.NAS 线性扩容性  高  差  差 文件高并发访问性能 高 差  一般 文件访问方式 专有API POSIX  支持POSIX 硬件成 ...

  7. 【传智播客】Libevent学习笔记(四):事件event

    目录 00. 目录 01. 事件概述 02. 创建事件 03. 事件的标志 04. 事件持久性 05. 超时事件 06. 信号事件 07. 设置不使用堆分配的事件 08. 事件的未决和非未决 09. ...

  8. python 一些函数和类用法记录

    这一篇主要用来记录在学习过程中遇到的一些觉得有意思的函数或者类的用法,有一些用法感觉很炫酷. 1.collections.defaultdict from collections import def ...

  9. 3. 对系统表空间使用Raw磁盘分区

    3. 对系统表空间使用Raw磁盘分区 可以将raw磁盘分区用作InnoDB系统表空间中的数据文件.此技术可在Windows和某些Linux和Unix系统上启用非缓冲I/O,而无需文件系统开销.使用和不 ...

  10. c++_凑算式(最新方法)

    凑算式 B DEFA + --- + ------- = 10 C GHI (如果显示有问题,可以参见[图1.jpg]) 这个算式中A~I代表1~9的数字,不同的字母代表不同的数字. 比如:6+8/3 ...