valgrind使用_解决内存管理问题的最佳利器-valgrind

本文介绍Valgrind工具集中的memcheck工具,用于检测C/C++程序中的内存错误,如内存泄漏、非法访问等问题。文章包含快速入门指南、常见错误信息解析及QtCreator程序的调用实例。

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

Valgrind是开源免费的软件,基于GNU General Public License, version 2.

fbfefb9a703ff6519aebed27dc5ec2fd.png

一、快速入门

Valgrind工具集中最受欢迎的是memcheck, 它满足大部分的场景。memcheck能够检测内存相关的错误,并且是采用C/C++编译的程序,程序运行过程中奔溃或者不可预料的行为都可以使用Valgrind中的memcheck来进行检测。

使用Valgrind前,采用-g选项编译程序,这样memcheck才能够提取到具体的行号信息,同时可以使用-O0优化选项,但是如果使用-O1选项,那么显示的行号信息可能就不准确;不推荐使用-O2选项,如果使用的话,memcheck偶尔上报不是真的存在的未初始化的错误信息

命令行一般的使用格式如下所示,–leak-check=yes是打开内存泄露的检测器。

af864c7e930d9037ecbd8f33d9498ae2.png

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

6ebd867672cd94d280450eac6566800a.png

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

5b7bcf28f06290eedc6714bbd4652d05.png

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

54fdeff61e865230757478d61f3010de.png

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

8a9d11f866841eeb311cf94977a402d2.png

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

2e082c5b298260f016873b02247468b1.png

二、memcheck的错误信息

memcheck是内存错误的检测器,他可以检测C/C++常见的下列错误问题

  1. 访问不应该访问的内存,例如堆溢出、栈溢出、访问已经释放的内存
  2. 使用没有定义的值,例如值没有初始化
  3. 不正确的释放堆内存,例如重复释放内存,malloc/new/new[] 和 free/delete/delete[]没有一一对应使用
  4. 使用memcpy函数,源地址和目的地址重叠
  5. 向内存分配函数中,传递一个不正确的参数,例如负数
  6. 内存泄露
  • 非法读写错误,例如读取已经释放内存的地址,为了获取更多的信息,可以加上–read-var-info=yes的选项
8e4eb08364ad7293bfeac86c516ef8c4.png
  • 使用没有定义的值,例如定义了变量,但是没有初始化,如果信息不够详细,可以添加参数–track-origins=yes来获取更多的信息
c7992b96ad2d5949dfe1cea6edf1f5a1.png
8af90a033fcccbd70fdca0bf92bae0ab.png
  • 非法释放地址,例如重复释放内存
c16ba9aca2d7e0d28563ab6f696466a1.png
3ddc93b0e0bb2452123143612452e651.png
  • 调用申请和释放内存的方法不匹配,例如malloc申请内存,但是使用delete来释放,对某些系统来说是不允许的,因此,为了保证程序健壮,使用malloc,那么对应使用free; 使用new,那么对应使用delete; 使用new [], 那么对应使用delete []。
1199911db33c738f68f288b9e9dba6b9.png

三、Valgrind调用QtCreator程序

mac系统通过QtCreator创建程序之后,也可以采用Valgrind在终端上检测QtCreator生成的程序。

首先进入QtCreator编译生成的文件目录

a9057d5cd3f5f6cd86f6796a30d553fe.png

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

de412002a69ddd15d493e4414e245e1a.png

四、局限性

  1. Memcheck并不完美,它也会出现误报,但是它有99%的准确性,对于它提示的信息我们应该警惕。
  2. memcheck不能检测每一种内存错误,比如它不能检测到对静态分配或堆栈上的数组的超出范围的读写,但是它还是能够检测出使得你程序奔溃的错误,例如段错误segmentation fault

五、总结

程序开发过程中,可能会遇到崩溃的问题,如果代码量很多的时候,我们可能会使用gdb来查看coredump信息,但是有时候gdb的信息比较简单,没有更加详细的堆栈信息,那么就可以考虑使用Valgrind进行分析。

最近,工作中遇到一个问题,程序运行过程中,会偶发崩溃问题,使用gdb查看coredump信息,显示是重复释放内存,但是堆栈信息很少,一直找不到位置,后来使用Valgrind来查看程序,仔细查看Valgrind提供的堆栈信息,很快找到问题的位置,并确定是重复释放内存。

温馨提示:Valgrind经常上报了很多错误提示信息,这个可能是同样一个地方调用了多次,所以,如果解决了一个地方的问题,错误提示信息就会全部消失,需要耐心仔细。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值