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

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

valid- ad dress 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,没有释放内存 barret@Barret-PC:~$valgrind--leak-check=yes./a.out ==393==Memcheck,amem or yerrordetector ==393==UsingValgrind-3.15.0andLibVEX;rerunwith-hforcopyrigh ti nfo ==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- amd 64-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==stillre ac hable:0bytesin0blocks ==393==suppressed:0bytesin0blocks ==393== ==393==Forlistsofdetectedandsuppressederro rs ,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; ==427==Syscallparamexit_group(status)**cont ai nsuninitialisedbyte(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) ==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) 审核编辑:彭静 声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 一种利用调试软件 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 Linux C/C++ 内存 泄漏 检测 工具: Valgrind
Valgrind 是一款 Linux下(支持 x86、x86_64和ppc32)程序的 内存 调试工具,它可以对编译后的二进制程序进行 内存 使用监测(C语言中的malloc和free,以及
发表于 04-02 14:33 521 次阅读