Memcheck的错误信息详解

Memcheck的错误信息详解

Memcheck看似先进,实际上它只能检测出两种错误:非法地址的使用和使用了未定义的变量。但是足够帮助你发现代码里存在的内存问题。

* 非法读/写
例子:
====================================================
Invalid read of size 4
at 0x40F6BBCC: (within /usr/lib/libpng.so.2.1.0.9)
by 0x40F6B804: (within /usr/lib/libpng.so.2.1.0.9)
by 0x40B07FF4: read_png_image__FP8QImageIO (kernel/qpngio.cpp:326)
by 0x40AC751B: QImageIO::read() (kernel/qimage.cpp:3621)
Address 0xBFFFF0E0 is not stack’d, malloc’d or free’d
====================================================

提示:如果程序单独运行,会出现断错误的提示,并退出运行。但是在valgrind中是可以持续运行下去。


* 使用未初始化的变量
例子:
====================================================
Conditional jump or move depends on uninitialised value(s)
at 0x402DFA94: _IO_vfprintf (_itoa.h:49)
by 0x402E8476: _IO_printf (printf.c:36)
by 0x8048472: main (tests/manuel1.c:8)
====================================================

示例代码:
====================================================
int main()
{
int x;
printf ("x = %d\n", x);
}
====================================================

提示: 在valgrind检测时会报错,但是程序可以正确执行,x的值为内存随机值。

* 非法释放内存
例子:
====================================================
Invalid free()
at 0x4004FFDF: free (vg_clientmalloc.c:577)
by 0x80484C7: main (tests/doublefree.c:10)
Address 0x3807F7B4 is 0 bytes inside a block of size 177 free’d
at 0x4004FFDF: free (vg_clientmalloc.c:577)
by 0x80484C7: main (tests/doublefree.c:10)
====================================================

提示: 如果地址在这之前已经被释放了,你会收到多次释放的提示信息.

* malloc/free和new/delete不成对使用。
例子:
====================================================
Mismatched free() / delete / delete []
at 0x40043249: free (vg_clientfuncs.c:171)
by 0x4102BB4E: QGArray::~QGArray(void) (tools/qgarray.cpp:149)
by 0x4C261C41: PptDoc::~PptDoc(void) (include/qmemarray.h:60)
by 0x4C261F0E: PptXml::~PptXml(void) (pptxml.cc:44)
Address 0x4BB292A8 is 0 bytes inside a block of size 64 alloc’d
at 0x4004318C: __builtin_vec_new (vg_clientfuncs.c:152)
by 0x4C21BC15: KLaola::readSBStream(int) const (klaola.cc:314)
by 0x4C21C155: KLaola::stream(KLaola::OLENode const *) (klaola.cc:416)
by 0x4C21788F: OLEFilter::convert(QCString const &) (olefilter.cc:272)
====================================================

提示: 通常在C环境下,只可能是malloc和free。

* 传给系统调用的参数的读/写权限不够
例子:
====================================================
Syscall param write(buf) points to uninitialised byte(s)
at 0x25A48723: __write_nocancel (in /lib/tls/libc-2.3.3.so)
by 0x259AFAD3: __libc_start_main (in /lib/tls/libc-2.3.3.so)
by 0x8048348: (within /auto/homes/njn25/grind/head4/a.out)
Address 0x25AB8028 is 0 bytes inside a block of size 10 alloc’d
at 0x259852B0: malloc (vg_replace_malloc.c:130)
by 0x80483F1: main (a.c:5)
Syscall param exit(error_code) contains uninitialised byte(s)
at 0x25A21B44: __GI__exit (in /lib/tls/libc-2.3.3.so)
by 0x8048426: main (a.c:8)
====================================================

代码示例:
====================================================
#include <stdlib.h>
#include <unistd.h>
int main( void )
{
char* arr = malloc(10);
int* arr2 = malloc(sizeof(int));
write( 1 /* stdout */, arr, 10 );
exit(arr2[0]);
}
====================================================

提示: 上面的代码至少有三个错误,1)没有释放内存,2)没有初始化新申请的内存块就开始写入,3)没有初始化新申请的内存块就开始读取。
错误信息中的第一条指出了指向未初始化的内存块的指针。第二条才指出了未初始化的内存在什么地方。 第三条则是指出了系统调用退出时使用了未初始化的内存块的位置。

* 目标和源内存块发生了重叠
例子:
==================================================== 
==27492== Source and destination overlap in memcpy(0xbffff294, 0xbffff280, 21)
==27492== at 0x40026CDC: memcpy (mc_replace_strmem.c:71)
==27492== by 0x804865A: main (overlap.c:40)
==27492==
====================================================

提示: 由于内存拷贝函数的实现方式可能会在各个平台上有所不同,所以一定要注意不要随意重叠两个内存块。

* 内存泄漏
例子:
====================================================
8 bytes in 1 blocks are definitely lost in loss record 1 of 14
at 0x........: malloc (vg_replace_malloc.c:...)
by 0x........: mk (leak-tree.c:11)
by 0x........: main (leak-tree.c:39)
88 (8 direct, 80 indirect) bytes in 1 blocks are definitely lost
in loss record 13 of 14
at 0x........: malloc (vg_replace_malloc.c:...)
by 0x........: mk (leak-tree.c:11)
by 0x........: main (leak-tree.c:25)
====================================================

提示: 设置--leak-check=选项,来设置泄漏检测的级别。

Memcheck会给每个被检测内存块进行分类,共三类:
* Still reachable: 仍可访问的内存块,原则上应该在程序退出时进行释放。但是这是一个有争议的话题,memcheck不会将之报告为错误,除非设置了--show-reachable=yes才会看到该信息。

* Possible lost or "Dubious": 可能丢失的内存。memcheck可能是发现了一个指向某个内存块内部的指针,但是不确定该内存是否存在。原因可能在于该指针一开始是指向内存块的开始的,但是之后的一段时间该指针被移动,导致无法使用该指针对其内存进行释放。

* Definitly lost or "leaked": 可以确定是泄漏的内存。当memcheck找不到某个内存块被任何指针指向的时候,也就意味着该内存无法被释放。该错误通常不能忽略。


Memcheck只能指出被泄露的内存是在哪儿申请的,而并不能指出该内存是如何泄漏的。所以需要用户根据memcheck提供的栈跟踪结果来作出判断。


注意查看上述例子中的第二条错误,它指出有8字节的direct内存块和80字节的indirect内存块是确定泄漏的。那么,什么是direct内存块和indirect内存块呢?direct内存块是指内存块不被任何指针所指向;而indirect内存块则是被另一个泄漏的内存块里的指针所指向。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值