Valgrind是一个动态分析工具,能够自动检测许多内存管理问题、线程bug, 并且能够分析程序的状况。它内部支持多个工具集,包括内存错误检测器,线程错误检测器,缓存分析器、堆分析器等,默认使用的是内存检测器(memcheck), 它是使用最多的一个内存检测工具, 当然,你也可以基于Valgrind自己建立新的工具。
Valgrind是开源免费的软件,基于GNU General Public License, version 2.

一、快速入门
Valgrind工具集中最受欢迎的是memcheck, 它满足大部分的场景。memcheck能够检测内存相关的错误,并且是采用C/C++编译的程序,程序运行过程中奔溃或者不可预料的行为都可以使用Valgrind中的memcheck来进行检测。
使用Valgrind前,采用-g选项编译程序,这样memcheck才能够提取到具体的行号信息,同时可以使用-O0优化选项,但是如果使用-O1选项,那么显示的行号信息可能就不准确;不推荐使用-O2选项,如果使用的话,memcheck偶尔上报不是真的存在的未初始化的错误信息
命令行一般的使用格式如下所示,–leak-check=yes是打开内存泄露的检测器。

下面提供一个C++例子,该例子有内存泄露和访问不存在地址的两个错误

错误信息描述如下,表示访问不存在地址,第一行“Invalid write of size 4”表明什么类型错误,写数据到内存中,而该内存是不应该访问的。1066表示进程id号。如果错误的堆栈信息显示不够详细,那么可以加上选项–num-callers,再加上层级数量,比如–num-callers=20。

内存泄露的错误信息提示描述如下, 它会告诉你内存分配的位置,但是它不能告诉你内存为什么泄露。

一般有几种内存泄露的类型,比较重要的两种是definitely lost和possibly lost,definitely lost是确定内存泄露,需要修复它,possibly lost可能存在内存泄露,需要仔细确认

另外memcheck比较经常会上报没有初始化值的信息,但是要定位到错误信息的根本原因是比较困难的,对此,可以添加参数–track-origins=yes来获取更多的信息,但是,这样会使得memcheck运行的更慢。

二、memcheck的错误信息
memcheck是内存错误的检测器,他可以检测C/C++常见的下列错误问题
- 访问不应该访问的内存,例如堆溢出、栈溢出、访问已经释放的内存
- 使用没有定义的值,例如值没有初始化
- 不正确的释放堆内存,例如重复释放内存,malloc/new/new[] 和 free/delete/delete[]没有一一对应使用
- 使用memcpy函数,源地址和目的地址重叠
- 向内存分配函数中,传递一个不正确的参数,例如负数
- 内存泄露
- 非法读写错误,例如读取已经释放内存的地址,为了获取更多的信息,可以加上–read-var-info=yes的选项

- 使用没有定义的值,例如定义了变量,但是没有初始化,如果信息不够详细,可以添加参数–track-origins=yes来获取更多的信息


- 非法释放地址,例如重复释放内存


- 调用申请和释放内存的方法不匹配,例如malloc申请内存,但是使用delete来释放,对某些系统来说是不允许的,因此,为了保证程序健壮,使用malloc,那么对应使用free; 使用new,那么对应使用delete; 使用new [], 那么对应使用delete []。

三、Valgrind调用QtCreator程序
mac系统通过QtCreator创建程序之后,也可以采用Valgrind在终端上检测QtCreator生成的程序。
首先进入QtCreator编译生成的文件目录

接着选择build开头的目录,右键弹出的列表选择“服务”->”新建位于文件夹位置的终端窗口”来启动终端, 终端输入如下所示的命令来使用Valgrind测试QtCreator编译生成的程序JQtTestStudy.app

四、局限性
- Memcheck并不完美,它也会出现误报,但是它有99%的准确性,对于它提示的信息我们应该警惕。
- memcheck不能检测每一种内存错误,比如它不能检测到对静态分配或堆栈上的数组的超出范围的读写,但是它还是能够检测出使得你程序奔溃的错误,例如段错误segmentation fault
五、总结
程序开发过程中,可能会遇到崩溃的问题,如果代码量很多的时候,我们可能会使用gdb来查看coredump信息,但是有时候gdb的信息比较简单,没有更加详细的堆栈信息,那么就可以考虑使用Valgrind进行分析。
最近,工作中遇到一个问题,程序运行过程中,会偶发崩溃问题,使用gdb查看coredump信息,显示是重复释放内存,但是堆栈信息很少,一直找不到位置,后来使用Valgrind来查看程序,仔细查看Valgrind提供的堆栈信息,很快找到问题的位置,并确定是重复释放内存。
温馨提示:Valgrind经常上报了很多错误提示信息,这个可能是同样一个地方调用了多次,所以,如果解决了一个地方的问题,错误提示信息就会全部消失,需要耐心仔细。
本文介绍Valgrind工具集中的memcheck工具,用于检测C/C++程序中的内存错误,如内存泄漏、非法访问等问题。文章包含快速入门指南、常见错误信息解析及QtCreator程序的调用实例。
2570

被折叠的 条评论
为什么被折叠?



