作者: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. dede网站目录权限设置

    如果你的网站数据十分重要(那种两天就能弄好的垃圾站就算了),建议按本文所说的安全步骤进行严格的设置.1.目录权限 我们不建议用户把栏目目录设置在根目录, 原因是这样进行安全设置会十分的麻烦, 在默认的 ...

  2. 4.03 使用NULL代替默认值

    问题:在一个定义了默认值的列插入数据,并且需要不管该列的默认值是什么,都将该列值设为NULL.考虑一下下面的表: create table D (id interger default 0, foo ...

  3. VINS-Fusion代码阅读(四)

    pts_i和pts_j:具体指什么含义?(分别为第l个路标点在第i, j个相机归一化相机坐标系中的观察到的坐标,P¯¯¯cil \bar{P}^{c_i}_l Pˉ lc i​ ​ 和 P¯¯¯cjl ...

  4. CNN完成mnist数据集手写数字识别

    # coding: utf-8 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data d ...

  5. 从零开始--系统深入学习Android

    http://www.cnblogs.com/tianjian/category/354587.html

  6. 实现验证的vsftpd虚拟用户

    实现基于文件验证的vsftpd虚拟用户--(一台) 一.创建用户数据库文件 vim /etc/vsftpd/vuser cd /etc/vsftpd/ db_load -T -t hash -f vu ...

  7. BERT模型介绍

    前不久,谷歌AI团队新发布的BERT模型,在NLP业内引起巨大反响,认为是NLP领域里程碑式的进步.BERT模型在机器阅读理解顶级水平测试SQuAD1.1中表现出惊人的成绩:全部两个衡量指标上全面超越 ...

  8. 剑指Offer(书):矩阵中的路径

    题目: * 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.* 路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.* 如果一条路径经 ...

  9. 3.3.3 使用 join 连接字段

        join 命令可以将多个文件结合在一起,每个文件里的每条记录,都共享一个键值(key),键值指的是记录中的主字段,通常会是用户名称.个人姓氏.员工编号之类的数据.举例来说,两个文件,一个列出所 ...

  10. 如何根据实体动态生成sql语句

    该文章同时解决了,如何向数据库中添加Null值,以及如何处理“参数化查询未提供参数”的错误.解决方案请看第二段折叠的代码. 背景: 在项目开发的过程中,往往需要根据实体的值来修改sql语句,比如说,有 ...