Explanation of error messages from Memcheck

来源:互联网 发布:淘宝网店申请注册 编辑:程序博客网 时间:2024/05/22 12:40

 Excerpt from Valgrind documentation

3.3  Explanation of error messages from Memcheck

Despite considerable sophistication under the hood, Memcheck can onlyreally detect two kinds of errors, use of illegal addresses, and useof undefined values. Nevertheless, this is enough to help youdiscover all sorts of memory-management nasties in your code. Thissection presents a quick summary of what error messages mean.

3.3.1  Illegal read / Illegal write errors

For example:

  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

This happens when your program reads or writes memory at a placewhich Memcheck reckons it shouldn't. In this example, the program dida 4-byte read at address 0xBFFFF0E0, somewhere within thesystem-supplied library libpng.so.2.1.0.9, which was called fromsomewhere else in the same library, called from line 326 ofqpngio.cpp, and so on.

Memcheck tries to establish what the illegal address might relateto, since that's often useful. So, if it points into a block ofmemory which has already been freed, you'll be informed of this, andalso where the block was free'd at. Likewise, if it should turn outto be just off the end of a malloc'd block, a common result ofoff-by-one-errors in array subscripting, you'll be informed of thisfact, and also where the block was malloc'd.

In this example, Memcheck can't identify the address. Actually theaddress is on the stack, but, for some reason, this is not a validstack address -- it is below the stack pointer, %esp, and that isn'tallowed. In this particular case it's probably caused by gccgenerating invalid code, a known bug in various flavours of gcc.

Note that Memcheck only tells you that your program is about toaccess memory at an illegal address. It can't stop the access fromhappening. So, if your program makes an access which normally wouldresult in a segmentation fault, you program will still suffer the samefate -- but you will get a message from Memcheck immediately prior tothis. In this particular example, reading junk on the stack isnon-fatal, and the program stays alive.

3.3.2  Use of uninitialised values

For example:

  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)
by 0x402A6E5E: __libc_start_main (libc-start.c:129)

An uninitialised-value use error is reported when your program usesa value which hasn't been initialised -- in other words, is undefined.Here, the undefined value is used somewhere inside the printf()machinery of the C library. This error was reported when running thefollowing small program:

  int main()
{
int x;
printf ("x = %d/n", x);
}

It is important to understand that your program can copy aroundjunk (uninitialised) data to its heart's content. Memcheck observesthis and keeps track of the data, but does not complain. A complaintis issued only when your program attempts to make use of uninitialiseddata. In this example, x is uninitialised. Memcheck observes thevalue being passed to _IO_printf and thence to _IO_vfprintf, but makesno comment. However, _IO_vfprintf has to examine the value of x so itcan turn it into the corresponding ASCII string, and it is at thispoint that Memcheck complains.

Sources of uninitialised data tend to be:

  • Local variables in procedures which have not been initialised, as in the example above.
  •  

  • The contents of malloc'd blocks, before you write something there. In C++, the new operator is a wrapper round malloc, so if you create an object with new, its fields will be uninitialised until you (or the constructor) fill them in, which is only Right and Proper.

3.3.3  Illegal frees

For example:

  Invalid free()
at 0x4004FFDF: free (vg_clientmalloc.c:577)
by 0x80484C7: main (tests/doublefree.c:10)
by 0x402A6E5E: __libc_start_main (libc-start.c:129)
by 0x80483B1: (within tests/doublefree)
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)
by 0x402A6E5E: __libc_start_main (libc-start.c:129)
by 0x80483B1: (within tests/doublefree)

Memcheck keeps track of the blocks allocated by your program withmalloc/new, so it can know exactly whether or not the argument tofree/delete is legitimate or not. Here, this test program hasfreed the same block twice. As with the illegal read/write errors,Memcheck attempts to make sense of the address free'd. If, ashere, the address is one which has previously been freed, you wilbe told that -- making duplicate frees of the same block easy to spot.

3.3.4  When a block is freed with an inappropriatedeallocation function

In the following example, a block allocated with new[]has wrongly been deallocated with free

:

  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)

The following was told to me be the KDE 3 developers. I didn't knowany of it myself. They also implemented the check itself.

In C++ it's important to deallocate memory in a way compatible withhow it was allocated. The deal is:

  • If allocated with malloc, calloc, realloc, valloc or memalign, you must deallocate with free.
  • If allocated with new[], you must deallocate with delete[].
  • If allocated with new, you must deallocate with delete.

The worst thing is that on Linux apparently it doesn't matter if youdo muddle these up, and it all seems to work ok, but the same programmay then crash on a different platform, Solaris for example. So it'sbest to fix it properly. According to the KDE folks "it's amazing howmany C++ programmers don't know this".

Pascal Massimino adds the following clarification:delete[] must be called associated with anew[] because the compiler stores the size of the arrayand the pointer-to-member to the destructor of the array's contentjust before the pointer actually returned. This implies avariable-sized overhead in what's returned by new ornew[]. It rather surprising how compilers [Ed:runtime-support libraries?] are robust to mismatch innew/deletenew[]/delete[].

3.3.5  Passing system call parameters with inadequateread/write permissions

Memcheck checks all parameters to system calls. If a system callneeds to read from a buffer provided by your program, Memcheck checksthat the entire buffer is addressible and has valid data, ie, it isreadable. And if the system call needs to write to a user-suppliedbuffer, Memcheck checks that the buffer is addressible. After thesystem call, Memcheck updates its administrative information toprecisely reflect any changes in memory permissions caused by thesystem call.

Here's an example of a system call with an invalid parameter:

  #include <stdlib.h>
#include <unistd.h>
int main( void )
{
char* arr = malloc(10);
(void) write( 1 /* stdout */, arr, 10 );
return 0;
}

You get this complaint ...

  Syscall param write(buf) contains uninitialised or unaddressable byte(s)
at 0x4035E072: __libc_write
by 0x402A6E5E: __libc_start_main (libc-start.c:129)
by 0x80483B1: (within tests/badwrite)
by <bogus frame pointer> ???
Address 0x3807E6D0 is 0 bytes inside a block of size 10 alloc'd
at 0x4004FEE6: malloc (ut_clientmalloc.c:539)
by 0x80484A0: main (tests/badwrite.c:6)
by 0x402A6E5E: __libc_start_main (libc-start.c:129)
by 0x80483B1: (within tests/badwrite)

... because the program has tried to write uninitialised junk fromthe malloc'd block to the standard output.

3.3.6  Overlapping source and destination blocks

The following C library functions copy some data from one memory blockto another (or something similar): memcpy(),strcpy(), strncpy(), strcat(),strncat(). The blocks pointed to by their src anddst pointers aren't allowed to overlap. Memcheck checksfor this.

For example:

==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== by 0x40246335: __libc_start_main (../sysdeps/generic/libc-start.c:129)
==27492== by 0x8048470: (within /auto/homes/njn25/grind/head6/memcheck/tests/overlap)
==27492==

You don't want the two blocks to overlap because one of them could getpartially trashed by the copying.

原创粉丝点击