0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

valgrind检测内存问题的原理

嵌入式应用研究院 来源:嵌入式应用研究院 2023-05-23 09:30 次阅读

1、valgrind检测原理

valgrind 是一个提供了一些 debug 和优化的工具的工具箱,可以使得你的程序减少内存泄漏或者错误访问。valgrind 默认使用 memcheck 去检查内存问题。memcheck 检测内存问题的原理如下图所示:

469125e8-f8f5-11ed-90ce-dac502259ad0.png

Memcheck 能够检测出内存问题,关键在于其建立了两个全局表。

valid-value map:对于进程的整个地址空间中的每一个字节(byte),都有与之对应的 8 个 bits;对于 CPU 的每个寄存器,也有一个与之对应的 bit 向量。这些 bits 负责记录该字节或者寄存器值是否具有有效的、已初始化的值。

valid-address map:对于进程整个地址空间中的每一个字节(byte),还有与之对应的 1 个 bit,负责记录该地址是否能够被读写。在两个全局表的基础上,以如下方式进行检测:

当要读写内存中某个字节时,首先检查 valid-address map 中这个字节对应的 A bit。

如果该A bit显示该位置是无效位置,memcheck 则报告读写错误。内核(core)类似于一个虚拟的 CPU 环境,这样当内存中的某个字节被加载到真实的 CPU 中时,该字节对应的 V bit (在 valid-value map 中) 也被加载到虚拟的 CPU 环境中。一旦寄存器中的值,被用来产生内存地址,或者该值能够影响程序输出,则 memcheck 会检查对应的 V bits,如果该值尚未初始化,则会报告使用未初始化内存错误。

不过valgrind也不是万能的,对于栈上的内存空间操作就无法检测到。

2、命令选项

基本命令:valgrind --leak-check=yes ./a.out arg1 arg2

为了能够定位到源代码的行,建议编译时加上-g选项,并选择O0优化

3、使用示例

示例代码:

#include
intmain()
{
int*x=(int*)malloc(10*sizeof(int));
x[10]=1;//问题1,越界了
return0;//问题2,没有释放内存
}

执行valgrind检测后的结果:

barret@Barret-PC:~$valgrind--leak-check=yes./a.out
==393==Memcheck,amemoryerrordetector
==393==Copyright(C)2002-2017,andGNUGPL'd,byJulianSewardetal.
==393==UsingValgrind-3.15.0andLibVEX;rerunwith-hforcopyrightinfo
==393==Command:./a.out
==393==
==393==Invalidwriteofsize4
==393==at0x10916B:main(a.cpp:6)
==393==Address0x4a47068is0bytesafterablockofsize40alloc'd
==393==at0x483B7F3:malloc(in/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==393==by0x10915E:main(a.cpp:5)
==393==
==393==
==393==HEAPSUMMARY:
==393==inuseatexit:40bytesin1blocks
==393==totalheapusage:1allocs,0frees,40bytesallocated
==393==
==393==40bytesin1blocksaredefinitelylostinlossrecord1of1
==393==at0x483B7F3:malloc(in/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==393==by0x10915E:main(a.cpp:5)
==393==
==393==LEAKSUMMARY:
==393==definitelylost:40bytesin1blocks
==393==indirectlylost:0bytesin0blocks
==393==possiblylost:0bytesin0blocks
==393==stillreachable:0bytesin0blocks
==393==suppressed:0bytesin0blocks
==393==
==393==Forlistsofdetectedandsuppressederrors,rerunwith:-s
==393==ERRORSUMMARY:2errorsfrom2contexts(suppressed:0from0)

结果解析如下:

==393==:执行程序的进程ID

Invalid write of size 4:表示发现一个错误,这里显示源代码第6行有错误,这里很明显是越界了,所以显示invalid write错误

40 bytes in 1 blocks are definitely lost in loss record 1 of 1:内存泄露错误,泄漏的大小是10* sizeof(int)40byte。

LEAK summary也会显示内存泄漏的情况

4、分析常见内存问题

4.1、写入非法内存地址

上面的例子已经展示了这种情况,访问分配的内存区域之外的空间,valgrind会上报如下的错误:

Invalid

write of size x

后跟调用栈信息

4.2、读取非法内存地址

和上一个情况类似,不同 的是读取而不是写入,错误信息如下:

Invalid

read of size x

后跟调用栈信息

4.3、读取未初始化内存区域

#include

intmain()
{
int*x=(int*)malloc(10*sizeof(int));
inta=x[1]+1;//不初始化就使用内存的值
free(x);
returna;
}

valgrind显示如下错误:

==427==Syscallparamexit_group(status)**containsuninitialisedbyte(s)**
==427==at0x4938136:Exit(exit.c:31)
==427==by0x489BB41:__run_exit_handlers(exit.c:132)
==427==by0x489BBDF:exit(exit.c:139)
==427==by0x48790B9:(belowmain)(libc-start.c:342)

4.4、内存双重释放

示例:

#include

intmain()
{
int*x=(int*)malloc(10*sizeof(int));
free(x);//free两次
free(x);
return0;
}

valgrind显示如下错误,显示两次free的位置:

==436==Invalidfree()/delete/delete[]/realloc()
==436==**at0x483CA3F:free(in/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==436==by0x10919A:main(a.cpp:7)
==436==Address0x4a47040is0bytesinsideablockofsize40free'd
==436==at0x483CA3F:free(in/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==436==by0x10918E:main(a.cpp:6)**
==436==Blockwasalloc'dat
==436==at0x483B7F3:malloc(in/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==436==by0x10917E:main(a.cpp:5)
审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内存
    +关注

    关注

    8

    文章

    3008

    浏览量

    73918
  • 程序
    +关注

    关注

    116

    文章

    3779

    浏览量

    80894
  • Valgrind
    +关注

    关注

    0

    文章

    9

    浏览量

    6797

原文标题:Linux内存泄漏调试利器-valgrind

文章出处:【微信号:嵌入式应用研究院,微信公众号:嵌入式应用研究院】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    检测内存泄漏和内存违例,Valgrind不可少!

    Valgrind可以检测内存泄漏和内存违例,但是用Valgrind生成的日志信息结合kcachegrind就可以查看C程序的执行线路图,调用
    的头像 发表于 05-07 08:45 6421次阅读
    <b class='flag-5'>检测</b><b class='flag-5'>内存</b>泄漏和<b class='flag-5'>内存</b>违例,<b class='flag-5'>Valgrind</b>不可少!

    使用valgrind对代码进行内存泄露检测

    代码可能存在内存泄露怎么办?
    发表于 08-21 15:30 384次阅读
    使用<b class='flag-5'>valgrind</b>对代码进行<b class='flag-5'>内存</b>泄露<b class='flag-5'>检测</b>

    嵌入式相关的动态检测工具Valgrind简介

    Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。
    的头像 发表于 11-08 09:41 1799次阅读
    嵌入式相关的动态<b class='flag-5'>检测</b>工具<b class='flag-5'>Valgrind</b>简介

    一种利用调试软件Valgrind进行嵌入式应用程序错误查找的技术

    本文介绍了一种利用调试软件Valgrind进行嵌入式应用程序错误查找的技术,利用它可以高效、自动地查找出程序中的多种错误。首先介绍了嵌入式程序常见错误,接着研究了Valgrind的工作原理,介绍了利用Valgrind进行程序错误
    发表于 04-23 06:49

    valgrind是怎样去移植源码的

    嵌入式内存检测工具-valgrind移植源码较快)准备:解压tar -jxvf valgrind-3.16.1.tar.bz2进入valgrind
    发表于 12-17 07:56

    写了一个内存泄漏检查工具

    嵌入式环境内存泄漏检查比较麻烦,valgrind比较适合于在pc上跑,嵌入式上首先移植就很麻烦,移植完了内存比较小,跑起来也比较费劲。所以手动写了一个内存泄漏检查工具,基本思路是,ho
    发表于 12-17 08:25

    如何编译使用内存泄漏的定位工具

    1.我们知道有个内存泄漏的定位工具: valgrind, 非常优秀。现在已经支持arm版本,下面看看如何编译使用:2.下载源码:
    发表于 12-17 08:13

    Linux C/C++内存泄漏检测工具:Valgrind

    Valgrind 是一款 Linux下(支持 x86、x86_64和ppc32)程序的内存调试工具,它可以对编译后的二进制程序进行内存使用监测(C语言中的malloc和free,以及
    发表于 04-02 14:33 603次阅读

    电脑的内存频率该如何检测

    ,选购电脑内存条的时候,需要检测电脑的内存频率,那么一个电脑的内存频率到底该如何检测呢,下面跟小编去学习几招轻松解决
    发表于 06-14 10:55 2074次阅读

    内存泄漏的检测方法

    的。其实不然,防止内存泄露要从良好的编程习惯做起,另外重要的一点就是要加强单元测试(Unit Test),而valgrind就是这样一款优秀的工具。
    的头像 发表于 06-20 11:01 3128次阅读

    使用valgrind的callgrind工具进行多线程性能分析

    valgrind是开源的性能分析利器。 根据它的文档,可以用它来检查内存泄漏等问题,还可以用来生成函数的调用图,就这两个功能就足够有吸引力了。
    的头像 发表于 06-22 09:51 2945次阅读

    valgrind基本功能介绍、基础使用方法说明

    Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。
    的头像 发表于 11-14 12:40 2405次阅读

    如何使用valgrind对代码进行内存泄露检测

    代码可能存在 内存泄露 怎么办? 使用 valgrind 可以对代码进行内存泄露检测valgrind下载安装 安装: 1 、tar –j
    的头像 发表于 10-04 14:56 815次阅读
    如何使用<b class='flag-5'>valgrind</b>对代码进行<b class='flag-5'>内存</b>泄露<b class='flag-5'>检测</b>

    如何发现内存泄漏

    检测两个角度介绍在 Linux 环境进行内存泄漏检测的方法,并重点介绍静态分析工具 BEAM、动态监测工具 Valgrind 和 rational purify 的使用方法。相信通过本
    的头像 发表于 11-13 15:41 574次阅读

    如何检测内存泄漏

    检测内存泄漏是软件开发过程中一项至关重要的任务,它有助于识别和解决那些导致程序占用过多内存资源,从而影响程序性能甚至导致程序崩溃的问题。以下将详细阐述几种常见的内存泄漏
    的头像 发表于 07-30 11:50 1647次阅读