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
次阅读