文章目录

  • 1 前言
  • 2 常用内存检测工具
  • 3 Valgrind工具
  • 4 使用Valgrind工具检测内存
    • 4.1 Valgrind安装
    • 4.2 使用说明
    • 4.3 检测程序使用空指针
    • 4.4 检测程序使用野指针
    • 4.5 检测程序内存空间访问越界
    • 4.6 检测程序内存空间未释放
    • 4.7 检测程序内存空间重复释放
    • 4.8 检测程序内存空间申请与释放不匹配
    • 4.9 小结
  • 5 参考文章

1 前言

  C/C++相比其他高级编程语言,具有指针的概念,指针即是内存地址。C/C++可以通过指针来直接访问内存空间,效率上的提升是不言而喻的,是其他高级编程语言不可比拟的;比如访问内存一段数据,通过指针可以直接从内存空间读取数据,避免了中间过程函数压栈、数据拷贝甚至消息传输等待。指针是C/C++的优势,但也是一个隐患,指针是一把双刃剑,由于内存交给了程序员管理,这是存在隐患的;人嘛总会有疏忽的时候,如果申请了内存,一个疏忽忘记释放了,未释放的内存将不能被系统再申请使用,即是一直占用又不能使用,俗称内存泄露;久而久之,系统长时间运行后将申请不到内存,系统上所有任务执行失败,只能重启系统。内存交给了程序员管理,除了内存泄露的情况外,还可能引起其他的问题,总结起来包括如下几点。

  • 访问没有申请内存的空指针(空指针)
  • 访问已释放内存的指针(野指针)
  • 内存越界访问
  • 内存泄露,申请了内存没有释放
  • 重复释放内存

  虽然动态内存(这里默认指的是堆上的动态内存,由程序员管理;栈上的动态内存由系统管理)存在一定的隐患,可靠性取决于程序员的认真和细心,但因为其具有优良的灵活性和高效率以及内存复用,在实际应用中,对于一些动态数据交互场合,动态内存往往是首选。因此,一方面除了程序员本身的谨慎使用,另一方面也涌现出各类“内存异常“的检测工具,毕竟当代码量数以万计时,依靠人力去检查是不切实际的。

2 常用内存检测工具

  虽然动态内存存在隐患,但有时候又不得不使用,内存泄露也就成为一个必须杜绝的敏感问题;有需求就会有相应的解决方法,目前已存在许多优秀的内存泄露检测工具,除了我们常用的Valgrind外,还有mtrace、dmalloc、memwatch等优秀工具。

工具 描述
valgrind 一个强大开源的程序检测工具集合
mtrace GNU扩展, 用来跟踪malloc, mtrace为内存分配函数(malloc, realloc, memalign, free)安装hook函数
dmalloc 用于检查C/C++内存泄露(leak)的工具,即检查是否存在直到程序运行结束还没有释放的内存,以一个运行库的方式发布
memwatch 和dmalloc一样,它能检测未释放的内存、同一段内存被释放多次、位址存取错误及不当使用未分配之内存区域
mpatrol 一个跨平台的 C++ 内存泄漏检测器
dbgmem
Electric Fence

3 Valgrind工具

  Valgrind是一款基于linux平台开源的内存检测工具集合,功能强大,使用广泛。利用Valgrind工具,在检测出文章开头提及的动态内存隐患,即是Valgrind工具中的内存检测组件Memcheck, Memcheck支持的功能包括:

  • 使用空指针
  • 使用野指针
  • 内存空间访问越界
  • 内存空间未释放
  • 内存空间重复释放
  • 内存空间申请和释放不匹配

  Valgrind功能强大,是一个工具集合,除了Memcheck工具外,还提供Cachegrind、Helgrind、Callgrind、Massif工具。

  • Cachegrind

  与gprof类似的分析工具,但它对程序的运行观察更是入微,能给我们提供更多的信息。和gprof不同,它不需要在编译源代码时附加特殊选项,但加上调试选项是推荐的。Callgrind收集程序运行时的一些数据,建立函数调用关系图,还可以有选择地进行cache模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。

  • Helgrind

   Cache分析器,它模拟CPU中的一级缓存I1,Dl和二级缓存,能够精确地指出程序中cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助。

  • Callgrind

  它主要用来检查多线程程序中出现的竞争问题。Helgrind寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为“Eraser”的竞争检测算法,并做了进一步改进,减少了报告错误的次数。不过,Helgrind仍然处于实验阶段。

  • Massif

   堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。

  • extension

  可以根据core提供的功能,编写自定义的内存调试工具 。

  以上工具集介绍引自Linux下几款C++程序中的内存泄露检查工具文章,更新详细的介绍可以阅读原文,总结得非常好。

4 使用Valgrind工具检测内存

  Valgrind内存检测的原理是,Valgrind实现一个程序运行的虚拟环境,待检测的应用程序在Valgrind的虚拟环境中运行,Valgrind能够实时监测程序中内存申请、使用、释放的情况,并记录一些正常运行的有效信息和可能存在内存异常的信息,输出到终端或者用户指定的文件中。

4.1 Valgrind安装

  Valgrind工具实用且使用广泛,大多数主流linux系统发行版都已集成Valgrind工具,在终端输入“valgrind”,如系统没有安装Valgrind工具会提示以下安装信息。

acuity@ubuntu:~$ valgrind
The program 'valgrind' is currently not installed. You can install it by typing:
sudo apt install valgrind

  Valgrind安装可以下载源码后安装,也通过系统源在线安装,Ubuntu推荐在线安装。

sudo apt install valgrind

  安装完成,输入“valgrind”命令,提示以下信息,表示安装成功。

acuity@ubuntu:~$ valgrind
valgrind: no program specified
valgrind: Use --help for more information.

4.2 使用说明

  • 待检测的程序编译时需加入"-g",保留调试信息
  • 检测命令格式:valgrind --tool=memcheck --leak-check=full ./file–leak-check=full表示检测所有内存泄露
  • 检测记录除了输出到终端,还可以输出到文件,这样可以监测程序长时间运行后出现异常,通过查阅文件记录分析问题
  • 更多的使用说明或者忘记命令时,可以执行valgrind -h查看帮助信息

4.3 检测程序使用空指针

例子uninit.c

#include <stdio.h>int main(int argc, char * argv [ ])
{   int *p = NULL;printf("address [0x%p]\r\n", p);*p = 0;return 0;
}

  访问空指针,特别是往空指针写数据时,基本会引起段错误(Segmentation fault ),此时系统会产生core dump 文件,通过 core dump文件结合GDB工具也很容易找出访问空指针的地方。

4.4 检测程序使用野指针

例子free.c

#include <stdio.h>
#include <stdlib.h>int main(int argc, char * argv [ ])
{   int *p = NULL;p = malloc(4);if (p == NULL){perror("malloc failed");}printf("address [0x%p]\r\n", p);free(p);*p = 0;return 0;
}

4.5 检测程序内存空间访问越界

例子over.c

#include <stdio.h>
#include <stdlib.h>int main(int argc, char * argv [ ])
{   int *p = NULL;p = malloc(4);if (p == NULL){perror("malloc failed");}printf("address [0x%p]\r\n", p);p[4] = 0;free(p);return 0;
}

4.6 检测程序内存空间未释放

例子leak.c

#include <stdio.h>
#include <stdlib.h>int main(int argc, char * argv [ ])
{   int *p = NULL;p = malloc(4);if (p == NULL){perror("malloc failed");}printf("address [0x%p]\r\n", p);return 0;
}

4.7 检测程序内存空间重复释放

例子refree.c

#include <stdio.h>
#include <stdlib.h>int main(int argc, char * argv [ ])
{   int *p = NULL;p = malloc(4);if (p == NULL){perror("malloc failed");}printf("address [0x%p]\r\n", p);free(p);free(p);return 0;
}

4.8 检测程序内存空间申请与释放不匹配

例子nolike.c

#include <stdio.h>
#include <stdlib.h>int main(int argc, char * argv [ ])
{   int *p = NULL;p = (int*)malloc(sizeof(int));if (p == NULL){perror("malloc failed");}printf("address [0x%p]\r\n", p);delete p;return 0;
}

4.9 小结

  内存泄露检测包括动态内存使用的规范性,根本的解决办法是程序员保持良好的编码习惯,使用动态内存时谨慎考虑,保证申请与释放的必然性。因为,一些隐晦的问题可能需要在特定条件下才会引起内存泄露,依赖于检测工具也是需要长时间运行软件才能发现。

  Valgrind—memcheck工具更多是用于检测内存泄露,空指针、野指针、内存越界、重复释放等问题,会引系统段错误(Valgrind),使用GDB结合系统产生的core dump文件,也能快速定位到调用位置。而内存泄露不会立即导致系统异常,只有运行一定时间后系统申请不到内存时才会引起异常。因此,借助Valgrind—memcheck工具来检测内存泄露是一个高效的方法之一。

5 参考文章

【1】Linux下几款C++程序中的内存泄露检查工具

【2】Valgrind学习总结

【代码质量】如何使用Valgrind检测内存泄漏相关推荐

  1. linux环境下QT程序内存泄露检测-Qt creator +Valgrind检测内存泄漏(linux)

    原文查看具体内容: Qt creator +Valgrind检测内存泄漏(linux)_枫影竹韵的博客-CSDN博客 一.说明 由于Qt creator和valgrind是相互独立的,所以需要安装va ...

  2. valgrind检测内存泄漏,gperftools,memwatch和性能优化Messy_Test

    yum -y install  valgrind 如何在windows使用valgrind_如何在windows下使用f2py_weixin_39621870的博客-CSDN博客 QNX下Valgri ...

  3. ubuntu下Qt Creator使用valgrind检测内存泄漏

    1.安装valgrind sudo apt-get install valgrind 2. Valgrind的使用 为了使valgrind发现的错误更精确,如能够定位到源代码行,建议在编译时加上-g参 ...

  4. 使用asan检测内存泄漏、堆栈溢出等问题

    一.使用过程 操作过程参考:链接 缘起:程序在移动端崩溃,mac端复现不了,于是在写个崩溃位置函数的调用demo,使用ASAN工具进行排查. 验证过程 1.代码 main.cpp #include & ...

  5. Valgrind——memcheck内存泄漏分析

    文章目录 概述 memcheck检测原理 内存泄露分类 明确泄露 间接泄漏 可能泄漏 仍可访达 其他的内存错误检查类型 非法读/写内存 使用未初始化的变量 系统调用传递不可访问或未初始化内存 不对应的 ...

  6. Android性能优化之利用强大的LeakCanary检测内存泄漏及解决办法

    本篇文章主要介绍了Android性能优化之利用LeakCanary检测内存泄漏及解决办法,有兴趣的同学可以了解一下. 目录 前言 什么是内存泄漏? 内存泄漏造成什么影响? 什么是LeakCanary? ...

  7. VC使用CRT调试功能来检测内存泄漏

    信息来源:csdn      C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:"最大的长处也可能成为最大的弱点",那么 C/C++ 应用程序正好印证 ...

  8. 如何在linux下检测内存泄漏

    1.开发背景 在 windows 下使用 VC 编程时,我们通常需要 DEBUG 模式下运行程序,而后调试器将在退出程序时,打印出程序运行过程中在堆上分配而没有释放的内存信息,其中包括代码文件名.行号 ...

  9. VC使用CRT调试功能检测内存泄漏(转载)

    /*********************************************************************************** 检测内存泄漏的基本工具是调试器 ...

  10. VC++ 6.0 中如何使用 CRT 调试功能来检测内存泄漏[转]

    /C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:"最大的长处也可能成为最大的弱点",那么 C/C++ 应用程序正好印证了这句话.在 C/C++ 应用程 ...

最新文章

  1. Error: Aesthetics must be either length 1 or the same as the data (5): fill
  2. System.arraycopy(src, srcPos, dest, destPos, length) 与 Arrays.copyOf(original, newLength)区别
  3. Java是否为整数_Java问题 输入一个数判定其是否为整数
  4. %date:~0,10%用法
  5. 数据驱动业务——梦想成真,只差一步
  6. 673. 最长递增子序列的个数
  7. 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 10丨换座位【难度中等】
  8. php上js实现ajax请求,原生JS如何实现Ajax通过POST方式与PHP进行交互的方法
  9. Android进程间通信(复习笔记)
  10. Java 反射(练习)
  11. TCP协议(标志位URG、PSH,定时器,连接的建立和断开)
  12. 2018杭州电子科技大学计算机研究生复试笔试编程题第三题
  13. mt4 指标 涨跌幅 颜色k线_通达信指标公式源码主图指标【仓k线】源码
  14. Tornado部署时那些奇怪的错误
  15. 关于水晶报表打包的一些注意的地方!
  16. VB.NET控件应用编程实例教程(奋斗的小鸟)_PDF 电子书
  17. Visual Studio 2022 WinForm/Wpf打包安装程序
  18. MDI格式文件的打开与转换(pdf)
  19. windows图片和传真查看器打不开的解决办法
  20. vscode编译、调试stm32F4系列mcu的程序

热门文章

  1. 如何使用iPhoneXR/XSMAX模拟器进行屏幕适配
  2. Ubuntu10.04正式版主目录加密BUG
  3. 如何在Mac上清理磁盘空间?
  4. GAT GAX 简介
  5. python selenium清除缓存,Selenium Python:无法清除chrome浏览器缓存
  6. python selenium清除缓存_SeleniumPython:无法清除chrome浏览器缓存
  7. Windows和ubuntu互传文件
  8. 修改macOS中鼠标滚轮方向
  9. 写在博士旅程之前|博士第一年|博士第三年|博士第四年
  10. wps文档设置页眉左右(奇偶页)不同内容