【代码质量】如何使用Valgrind检测内存泄漏
文章目录
- 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检测内存泄漏相关推荐
- linux环境下QT程序内存泄露检测-Qt creator +Valgrind检测内存泄漏(linux)
原文查看具体内容: Qt creator +Valgrind检测内存泄漏(linux)_枫影竹韵的博客-CSDN博客 一.说明 由于Qt creator和valgrind是相互独立的,所以需要安装va ...
- valgrind检测内存泄漏,gperftools,memwatch和性能优化Messy_Test
yum -y install valgrind 如何在windows使用valgrind_如何在windows下使用f2py_weixin_39621870的博客-CSDN博客 QNX下Valgri ...
- ubuntu下Qt Creator使用valgrind检测内存泄漏
1.安装valgrind sudo apt-get install valgrind 2. Valgrind的使用 为了使valgrind发现的错误更精确,如能够定位到源代码行,建议在编译时加上-g参 ...
- 使用asan检测内存泄漏、堆栈溢出等问题
一.使用过程 操作过程参考:链接 缘起:程序在移动端崩溃,mac端复现不了,于是在写个崩溃位置函数的调用demo,使用ASAN工具进行排查. 验证过程 1.代码 main.cpp #include & ...
- Valgrind——memcheck内存泄漏分析
文章目录 概述 memcheck检测原理 内存泄露分类 明确泄露 间接泄漏 可能泄漏 仍可访达 其他的内存错误检查类型 非法读/写内存 使用未初始化的变量 系统调用传递不可访问或未初始化内存 不对应的 ...
- Android性能优化之利用强大的LeakCanary检测内存泄漏及解决办法
本篇文章主要介绍了Android性能优化之利用LeakCanary检测内存泄漏及解决办法,有兴趣的同学可以了解一下. 目录 前言 什么是内存泄漏? 内存泄漏造成什么影响? 什么是LeakCanary? ...
- VC使用CRT调试功能来检测内存泄漏
信息来源:csdn C/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:"最大的长处也可能成为最大的弱点",那么 C/C++ 应用程序正好印证 ...
- 如何在linux下检测内存泄漏
1.开发背景 在 windows 下使用 VC 编程时,我们通常需要 DEBUG 模式下运行程序,而后调试器将在退出程序时,打印出程序运行过程中在堆上分配而没有释放的内存信息,其中包括代码文件名.行号 ...
- VC使用CRT调试功能检测内存泄漏(转载)
/*********************************************************************************** 检测内存泄漏的基本工具是调试器 ...
- VC++ 6.0 中如何使用 CRT 调试功能来检测内存泄漏[转]
/C++ 编程语言的最强大功能之一便是其动态分配和释放内存,但是中国有句古话:"最大的长处也可能成为最大的弱点",那么 C/C++ 应用程序正好印证了这句话.在 C/C++ 应用程 ...
最新文章
- Error: Aesthetics must be either length 1 or the same as the data (5): fill
- System.arraycopy(src, srcPos, dest, destPos, length) 与 Arrays.copyOf(original, newLength)区别
- Java是否为整数_Java问题 输入一个数判定其是否为整数
- %date:~0,10%用法
- 数据驱动业务——梦想成真,只差一步
- 673. 最长递增子序列的个数
- 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 10丨换座位【难度中等】
- php上js实现ajax请求,原生JS如何实现Ajax通过POST方式与PHP进行交互的方法
- Android进程间通信(复习笔记)
- Java 反射(练习)
- TCP协议(标志位URG、PSH,定时器,连接的建立和断开)
- 2018杭州电子科技大学计算机研究生复试笔试编程题第三题
- mt4 指标 涨跌幅 颜色k线_通达信指标公式源码主图指标【仓k线】源码
- Tornado部署时那些奇怪的错误
- 关于水晶报表打包的一些注意的地方!
- VB.NET控件应用编程实例教程(奋斗的小鸟)_PDF 电子书
- Visual Studio 2022 WinForm/Wpf打包安装程序
- MDI格式文件的打开与转换(pdf)
- windows图片和传真查看器打不开的解决办法
- vscode编译、调试stm32F4系列mcu的程序
热门文章
- 如何使用iPhoneXR/XSMAX模拟器进行屏幕适配
- Ubuntu10.04正式版主目录加密BUG
- 如何在Mac上清理磁盘空间?
- GAT GAX 简介
- python selenium清除缓存,Selenium Python:无法清除chrome浏览器缓存
- python selenium清除缓存_SeleniumPython:无法清除chrome浏览器缓存
- Windows和ubuntu互传文件
- 修改macOS中鼠标滚轮方向
- 写在博士旅程之前|博士第一年|博士第三年|博士第四年
- wps文档设置页眉左右(奇偶页)不同内容