Silencing Valgrind Errors

  • Follow


Valgrind will report errors if a program attempts to access
uninitialized memory.  Normally this is desirable debugging behavior.
But, Valgrind does not seem to consider  reading from disk a form of
initialization.  So if you allocate a block of memory, and then
immediately use it to read from disk with a low-level system call,
such as read or pread, and then later access that memory block, or
write it out to disk with write/pwrite, Valgrind thinks you are
writing out an uninitialized block of memory.

Obviously, this can be easily fixed with a call to memset before
reading from disk.  But that's unnecessary and inefficient.  Ideally,
I'd like to do a #ifdef which would initialize the memory block only
when the program is being run under Valgrind, in order to silence the
error.  Is there some published definition that can be used to do
this?  I tried #ifdef VALGRIND, but that didn't work.  I can't find
anything about it in the Valgrind manual either.

Any suggestions?
0
Reply chsalvia (83) 12/19/2007 7:11:30 PM

On Dec 19, 11:11 am, chsal...@gmail.com wrote:
> Valgrind will report errors if a program attempts to access
> uninitialized memory.  Normally this is desirable debugging behavior.
> But, Valgrind does not seem to consider  reading from disk a form of
> initialization.  So if you allocate a block of memory, and then
> immediately use it to read from disk with a low-level system call,
> such as read or pread, and then later access that memory block, or
> write it out to disk with write/pwrite, Valgrind thinks you are
> writing out an uninitialized block of memory.

Something is wrong with your understanding of the results you are
seeing or something is wrong with your installation of valgrind.
Perhaps, for example, your program is ignoring the return value from
'read' and writing the data out past the number of bytes read.

> Obviously, this can be easily fixed with a call to memset before
> reading from disk.  But that's unnecessary and inefficient.

Worse, that will prevent valgrind from doing its job. If you write out
35 bytes but only read in 12, you want to get an error.

> Ideally,
> I'd like to do a #ifdef which would initialize the memory block only
> when the program is being run under Valgrind, in order to silence the
> error.  Is there some published definition that can be used to do
> this?  I tried #ifdef VALGRIND, but that didn't work.  I can't find
> anything about it in the Valgrind manual either.

> Any suggestions?

Are you 100% sure this isn't a bug in your program? Did you check to
make sure you are reading to and writing from where you think you are?
Did you check to make sure the return value of 'read' ensures that
every byte you write out was actually read in?

If so, you have a bug in valgrind or a bad build of valgrind.

DS
0
Reply David 12/19/2007 7:32:29 PM


chsalvia wrote:

> Valgrind will report errors if a program attempts to access
> uninitialized memory.  Normally this is desirable debugging behavior.

Yes.

> But, Valgrind does not seem to consider reading from disk a form of
> initialization.  So if you allocate a block of memory, and then
> immediately use it to read from disk with a low-level system call,
> such as read or pread, and then later access that memory block, or
> write it out to disk with write/pwrite, Valgrind thinks you are
> writing out an uninitialized block of memory.

This is incorrect.

$ cat foo.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv)
{
   int fd, count, res; char buf[4000];
   if ((fd = open("/dev/zero", O_RDONLY)) < 0) return 1;
   if (argc < 2) count =  4000; else count = 50;
   res = read(fd, buf, count);
   printf("READ: %d\n", res);
   return buf[100];
}

$ gcc -O3 -Wall -ansi -pedantic foo.c

$ valgrind a.out
==26640== Memcheck, a memory error detector.
[...]
==26640==
--26640-- DWARF2 CFI reader: unhandled CFI instruction 0:50
--26640-- DWARF2 CFI reader: unhandled CFI instruction 0:50
READ: 4000
==26640==
==26640== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 1)
==26640== malloc/free: in use at exit: 0 bytes in 0 blocks.
==26640== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
==26640== For counts of detected errors, rerun with: -v
==26640== All heap blocks were freed -- no leaks are possible.

$ valgrind a.out xx
==26641== Memcheck, a memory error detector.
[...]
==26641==
--26641-- DWARF2 CFI reader: unhandled CFI instruction 0:50
--26641-- DWARF2 CFI reader: unhandled CFI instruction 0:50
READ: 50
==26641== Syscall param exit_group(exit_code) contains uninitialised byte(s)
==26641==    at 0x40C52AF: _Exit (in /lib/tls/libc-2.3.6.so)
==26641==    by 0x404DE1D: (below main) (in /lib/tls/libc-2.3.6.so)
==26641==
==26641== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 11 from 1)
==26641== malloc/free: in use at exit: 0 bytes in 0 blocks.
==26641== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
==26641== For counts of detected errors, rerun with: -v
==26641== All heap blocks were freed -- no leaks are possible.

In the first case, buf[100] was properly initialized by the read call,
but in the second case, it was not.

> Obviously, this can be easily fixed with a call to memset before
> reading from disk.  But that's unnecessary and inefficient.  Ideally,
> I'd like to do a #ifdef which would initialize the memory block only
> when the program is being run under Valgrind, in order to silence the
> error.

#ifdef is a compile-time mechanism. You'd need to make run-time checks
to decide whether your program is being run by valgrind or by a shell.

Regards.
0
Reply Spoon 12/20/2007 9:30:53 AM

2 Replies
30 Views

(page loaded in 0.164 seconds)


Reply: