Linux下内存检测利器Valgrind之Memcheck工具详解

news2024/11/27 20:32:36

目录

1、Valgrind简介

1.1、Memcheck工具

1.2、Callgrind工具

1.3、Cachegrind工具

1.4、Helgrind工具

1.5、Massif工具

2、如何使用Memcheck

2.1、启动Memcheck

2.2、输出消息解释

3、使用Memcheck检测内存问题实例

4、Valgrind和Memcheck其他命令选项

5、最后


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html       对于C/C++程序开发人员来说,程序中大部分问题都是与内存有关的,内存相关的bug会贯穿着整个软件开发与维护过程,有些内存问题排查起来会相当的困难,甚至会严重影响项目推进的进度。本文介绍Linux下的一款重量级调式与分析工具包Valgrind,并针对其中最常用的工具Memcheck的使用进行较详细的介绍。

1、Valgrind简介

        Valgrind是一套Linux下开放源代码(GPL V2)的仿真调试工具的集合,是运行在Linux 上的多用途代码分析和内存调试常用工具。Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其  他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。    

Valgrind支持的平台有:X86/Linux, AMD64/Linux, ARM/Linux, ARM64/Linux, PPC32/Linux, PPC64/Linux, PPC64LE/Linux, S390X/Linux, MIPS32/Linux, MIPS64/Linux, X86/Solaris, AMD64/Solaris, ARM/Android (2.3.x and later), ARM64/Android, X86/Android (4.0 and later), MIPS32/Android, X86/FreeBSD, AMD64/FreeBSD, X86/Darwin and AMD64/Darwin (Mac OS X 10.12).

       Valgrind被设计成非入侵式的工具,无须修改源程序或重新编译链接,直接对运行时的可执行程序进行检测。它包含Memcheck、Callgrind、Cachegrind、Helgrind和Massif等几大工具,其中Memcheck是最常用的工具,也是默认选项,即不指定使用哪个工具时就是使用Memcheck进行检查。  

       Valgrind的体系结构如下图所示:

如上图,Valgrind提供了Memcheck、Callgrind、Cachegrind、Helgrind和Massif等调试分析工具,每个工具执行某些类型的调试和分析任务,以排查和分析软件中存在的问题。

1.1、Memcheck工具

       这是Valgrind应用最广泛的一个工具,用来检测程序中多种内存问题,所有对内存的读写都会被监测到,一切对malloc、free、new、delete的调用都会被跟踪。该工具可以检测到如下的内存异常:

1)对未初始化内存的使用;
2)读/写已经释放了的内存块(引发内存访问违例);
3)读/写超出分配的内存块(内存越界);
4)读/写不适当的栈中内存块;
5)内存泄露;
6)malloc/free或者new/delete不匹配;
7)memcpy相关函数中的dst和src指针中内存地址重叠;

1.2、Callgrind工具

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

1.3、Cachegrind工具

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

1.4、Helgrind工具

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

1.5、Massif工具

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

       Massif对内存的分配和释放做profile。程序开发者通过它可以深入了解程序的内存使用行为,从而对内存使用进行优化。这个功能对C++尤其有用,因为C++有很多隐藏的内存分配和释放。

       Valgrind是基于仿真的方式对程序进行调试,它先于应用程序获取实际处理器的控制权,并在实际处理器的基础上仿真一个虚拟处理器,并使应用程序运行于这个虚拟处理器之上,从而对应用程序的运行进行监视。应用程序并不知道该处理器是虚拟的还是实际的,已经编译成二进制代码的应用程序并不用重新进行编译,Valgrind 直接解释二进制代码使得应用程序基于它运行,从而能够检查内存操作时可能出现的错误。所以,在Valgrind下运行的程序运行速度要慢的多,而且使用的内存比目标程序要多的多,这也是Valgrind的一大劣势,这也导致部分场合下没法使用Valgrind去分析。

2、如何使用Memcheck

       Memcheck是Valgrind中最常用的工具,下文将重点介绍它。

2.1、启动Memcheck

       要启动Memcheck工具,直接敲入以下命令:

[root@localhost ~]# valgrind --tool=memcheck ls -a

其中--tool选项指定需所使用的工具,后面跟所要检查的程序及其启动参数(如ls -a)。因为Memcheck是Valgrind工具包默认使用工具,因此上面命令可以直接写成如下形式:

[root@localhost ~]# valgrind ls -a

       这种形式,Valgrind会将检测结果直接输出到标准输出,如果所检查的程序也有标准输出的话,会夹杂在一起,阅读时容易造成混乱。使用如下方式启动将Valgrind检测结果输出到日志文件阅读时会比较清楚:

[root@localhost ~]# valgrind --tool=memcheck --log-file=filename ls –a

选--log-file用来指定输出的日志文件名,文件命中如果含有占位符%p,则实际生成的文件名该占位符将会被对应的进程号代替,这在检测多进程程序时比较有用,否则所有输出会写入一个单独的文件。

2.2、输出消息解释

       以上面最后一条命令为例,我们得到对应的输出文件,查看文件,内容如下:

输出消息的各部份说明见上图示,可以看到它把内存泄露分为以下几个等级:肯定的(definitely)、可能的(possibly)。

       另外,有个针对Memcheck的选项--leak-check=<no|summary|yes|full>,缺省值为summary即只给出泄露的摘要,如果设为yes或full,则会详细给出检查到的每个泄露的细节。

3、使用Memcheck检测内存问题实例

       下面结合具体的程序例子来检验Memcheck工具的效果,并对一些具体的输出消息作一下说明。先看一个特意编写的错误程序:

       敲入命令valgrind --tool=memcheck --leak-check=full --log-file=%pmemcheck ./valmemcheck后得到错误消息日志文件,为易于理解输出的错误消息,特意将源代码截图(右边)和错误消息截图(左边)放在一起,并用矩形框和连线把错误消息和对应的源代码对应起来,请放大参看下图:

基本上,大部分错误消息块分为两部分:上部分第一行指出错误类型,下面几行是函数调用栈回溯,这一部分也是比较重要的部分,直接提供给我们错误现场信息;对于有下部分的消息块,则其第一行指出具体错误涉及的内存地址,下面几行同样也是函数调用栈回溯。函数调用栈显示了函数所在源码行号,对于标准函数或库函数对应所在文件为vg_replace_xxx.c或mc_replace_xxx.c文件,我们可以不必理会,可以理解为Valgrind或Memcheck对这些库函数进行了hook。参见下面示意图:

       对于第一个错误引用未初始化的内存,看到消息块的上面部分函数调用栈并没有直接指出错误所在的源代码行号:

==12299== Syscall param write(buf) points to uninitialised byte(s)
==12299==    at 0x7990F3: __write_nocancel (in /lib/tls/libc-2.3.4.so)
==12299==    by 0x6F4DE2: (below main) (in /lib/tls/libc-2.3.4.so)
==12299==  Address 0x402b028 is 0 bytes inside a block of size 10 alloc'd
==12299==    at 0x4004A41: malloc (vg_replace_malloc.c:207)
==12299==    by 0x8048565: main (valmemcheck.cpp:8)

       Memcheck有个选项--track-origins=<yes|no>用来控制是否跟踪未初始化内存的原始创建地,默认为no。将该选项设为yes重新检查后,重新输出该错误的消息块如下:

==15781== Syscall param write(buf) points to uninitialised byte(s)
==15781==    at 0x7990F3: __write_nocancel (in /lib/tls/libc-2.3.4.so)
==15781==    by 0x6F4DE2: (below main) (in /lib/tls/libc-2.3.4.so)
==15781==  Address 0x402b028 is 0 bytes inside a block of size 10 alloc'd
==15781==    at 0x4004A41: malloc (vg_replace_malloc.c:207)
==15781==    by 0x8048565: main (valmemcheck.cpp:8)
==15781==  Uninitialised value was created by a heap allocation
==15781==    at 0x4004A41: malloc (vg_replace_malloc.c:207)
==15781==    by 0x8048565: main (valmemcheck.cpp:8)

可以看到增加了最后3行消息。

       结合错误日志和源码分析,可以判断所报的源和目的地址重叠问题基本上都准确,但内存泄露、malloc/new/new[]和free/delete/delete[]不匹配等错误,当内存地址指针通过几层函数调用传递后的情况,报告的错误不一定准确。

       需要注意的是,在用Memcheck工具检查程序时,内存泄露错误需要在程序正常退出时才会报告,函数中调用exit()、或非正常退出都不会报告该类错误;其他类型的错误如访问越界、地址重叠等在运行过程中如果发生会马上报告。

       此外,被检查的程序应该用debug版本,并且优化选项不能高于-O0,即编译选项为-g –O0。否则,Valgrind报告的错误所在源码行数会不准确。

4、Valgrind和Memcheck其他命令选项

       本篇对工具的介绍参考了Valgrind官方的User Manual,有些地方按照原文翻译,对存在的翻译不贴切之处欢迎大家提出建议,如果想了解更多更细的信息可直接上官方网站(http://valgrind.org)下载手册,或在Linux上敲valgrind --help或man valgrind命令查看相关帮助信息。如果所使用的Linux系统上没有该工具,可直接上其官方网站下载源码进行编译安装,本文就不一一展开了。

       除了上文已提到的主要常用的命令参数选项,Valgrind和Memcheck还有很多选项,此处列出仅为方便索引,如需使用,可查看相关文档。Valgrind的命令选项:

Memcheck的命令选项:

5、最后

       通过对实际程序的检查,可以看到Memcheck提供了全面的内存错误检查,报告的错误也比较准确,为Linux下程序调试提供了一种有效的手段。我们说Valgrind是一款“重量级”工具,不仅仅指它功能比较强,事实上它消耗内存和CPU也是“重量级”的,需要配置较高的机器才能跑的比较顺畅。对于服务器程序,挂上Valgrind后会吃大量内存,会严重拖慢程序的运行速度,可能会导致服务器业务没法正常进行,这时可能就要换AddressSanitizer等其他工具进行监测了。关于AddressSanitizer相关内容,可以参见我之前的文章:

为什么选择C/C++内存检测工具AddressSanitizer?如何使用AddressSanitizer?icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/132863447

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1096749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何处理前端错误和异常?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

【QT开发笔记-基础篇】| 第四章 事件QEvent | 4.6 定时器事件

本章要实现的整体效果如下&#xff1a; QT 中使用定时器&#xff0c;有两种方式&#xff1a; 定时器类&#xff1a;QTimer定时器事件&#xff1a;QEvent::Timer&#xff0c;对应的子类是 QTimerEvent 本节通过一个案例&#xff0c;同时讲解这两种方式 案例&#xff1a;当点击…

微信怎么加好友?竟然有5种方法!

微信是我们日常生活中不可缺少的通信工具。在我们的工作或者学习中&#xff0c;我们可能需要主动添加他人的微信来建立联系&#xff0c;以便日后进行更好地沟通。那微信怎么加好友呢&#xff1f;小编给大家总结了5种添加微信好友的方法&#xff01;没想到吧&#xff0c;居然有这…

低温下安装振弦采集仪注意事项

低温下安装振弦采集仪注意事项 振弦采集仪是一种用于测量和监测结构物振动状态的设备&#xff0c;通常用于桥梁、大型建筑物、风力发电机、船舰等设施的监测和评估。在一些寒冷地区&#xff0c;设施的使用环境会面临低温的挑战&#xff0c;因此在安装振弦采集仪时需要注意以下…

解决window电脑使用IKE VPN登录时显示上下文已过期,不能再用了的方法。

当电脑登录VPN时出现上下文已过期&#xff0c;不能再用了时解决办法。 1、使用 winR 的按键打打开运行&#xff1b; 2、输入 services.msc 在服务的列表中找到 IKE and AuthIP IPsec Keying Modules 这个服务&#xff0c;可以看到该服务为禁用状态下。 3、双击该服务&#xf…

论文复现:Active Learning by Learning

这篇文章说实在的&#xff0c;写的差强人意。 实质性内容是两个现有方法的拼凑&#xff01; 讲的模模糊糊&#xff01;对于复现代码不太友好&#xff01; 撸一点&#xff0c;通读一遍 &#xff0c;再撸一点&#xff0c;通读一遍~~~ """ 注意&#xff1a;使用…

Flutter 与 Dart 的市场应用

本文来自《2023年中国谷歌教育合作项目—武汉城市学院—面向Flutter框架的Dart语言师资培训与教学研讨》内容文字版。 Hello&#xff0c;大家好&#xff0c;我是 Flutter GDE 郭树煜&#xff0c;也是《Flutter 开发实战详解》的作者&#xff0c;同时也是 Github GSY 项目的负责…

VUE整合Echarts实现简单的数据可视化

提示&#xff1a;本篇案例使用的vue2 以及 vue cli脚手架&#xff1a; 文章目录 前言 一、Echarts的安装 二、可视化渲染 1.柱状图 2.饼图 3.主题的下载 总结 前言 ECharts是一款功能强大的前端数据可视化库&#xff0c;支持多种图表类型和统计图表、地理数据可视化、关系型…

超声波清洗机洗眼镜真的可以洗干净吗?眼镜超声波清洗机推荐

截止2023年4月份近视眼的统计&#xff0c;我过近视人群高达3亿人&#xff0c;可想而知现在近视的群体是有多么庞大的。近视就免不了要戴眼镜&#xff0c;但是一副眼镜长时间的佩戴不清洗的话&#xff0c;镜片会不清晰&#xff0c;也有的朋友会眼镜脏了就去配一副新的&#xff0…

【狂神说】HTML详解

目录 1 HTML概述1.1 什么是HTML1.2 HTML发展史1.3 HTML5的优势1.4 W3C标准 2 网页2.1 网页基本信息2.2 网页基本标签2.2.1 标题标签2.2.2 段落标签2.2.3 换行标签2.2.4 水平线标签2.2.5 字体样式标签&#xff1a;粗体、斜体2.2.6 注释和特殊符号 2.3 图像标签2.4 链接标签邮箱链…

MapGIS 10.6 Pro自主创新技术升级,护航国产化应用全面替代

信创GIS的发展历经雏形起步阶段&#xff08;2006-2013年&#xff09;、初步试点阶段&#xff08;2014-2017年&#xff09;、规模化试点阶段&#xff08;2017-2019年&#xff09;&#xff0c;目前正处在全面应用推广的新阶段&#xff08;2020年至今&#xff09;&#xff0c;当前…

九州未来参与编制的《基于C-V2X的智能化网联化融合发展路线图》正式发布!

近日&#xff0c;《基于C-V2X的智能化网联化融合发展路线图&#xff08;征求意见稿&#xff09;》在2023世界智能网联汽车大会上正式发布。 路线图在多位院士和众多行业专家指导下&#xff0c;由四十余家相关企业、高校、研究机构共同研究编制&#xff0c;十四家跨行业学会、联…

Seata入门系列【7】Seata之TCC模式入门案例

1 前言 Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 TCC 与 Seata AT 事务一样都是两阶段事务&#xff0c;它与 AT 事务的主要区别为&#xff1a; TCC 对业务代码侵入严重&#xff1a;每个阶段的数据操作都要自己进行…

PDF格式转换为翻页电子书,这种形式太酷辣!

PDF作为工作生活中最常见的文档格式之一&#xff0c;但是PDF格式阅读体验感不是那么好&#xff0c;这时候如果将PDF转化为翻页电子书再阅读&#xff0c;体验感不就直接拉满了嘛&#xff01;如何将PDF格式转换为翻页电子书呢&#xff1f; 为了解决这个问题&#xff0c;我们推荐…

国产数据库TiDB单机部署最佳实践

创建用户 ##创建用户 adduser tidb#设置密码 passwd tidb 配置免密码登录 cat >> /etc/sudoers << "EOF" tidb ALL(ALL) NOPASSWD:ALL EOF 创建tidb用户ssh key 切换用户 [rootjeames ~]# su - tidb 执行命令&#xff0c;一直按回车键就行 [tidbjeames…

官方认证:研发效能(DevOps)工程师职业技术认证

培养端到端的研发效能人才 为贯彻落实《关于深化人才发展体制机制改革的意见》&#xff0c;推动实施人才强国战略&#xff0c;促进专业技术人员提升职业素养、补充新知识新技能&#xff0c;实现人力资源深度开发&#xff0c;推动经济社会全面发展&#xff0c;根据《中华人民共…

build.gradle配置国内镜像源

maven { url https://maven.aliyun.com/repository/google/ } maven { url https://maven.aliyun.com/repository/jcenter/} maven { url https://jitpack.io }

【Eclipse】安装与卸载教程

目录 1.绿色版免安装版本 2.安装版本 3.卸载 首先打开官网&#xff1a;Eclipse Downloads | The Eclipse Foundation 选择download package 如图所示&#xff0c;到如下界面 1.绿色版免安装版本 按图片点击&#xff0c;即可开始下载 下载好后解压 &#xff0c;在桌面创建…

中青急速版更新(青龙脚本)

原脚本失效&#xff0c;请用新脚本&#xff0c;每天50毛左右见 实际运行情况见下图 中青入口&#xff1a;中青急速版软件入口 变量 export zqurlxxxxxxx 抓这个https://user.youth.cn/v1/user/userinfo.json?xxxxxx 脚本&#xff08;文件另存为zqjsf.py&#xff09; impor…

JAVA发送消息到RabbitMq

项目中&#xff0c;作为生产者自定义消息发送到RabbitMq。 1.引入rmq依赖 <!-- rabbitmq 依赖 --><dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.9.0</version></dependen…