Valgrind overrides pointer to integer promotion.

Today, a test file was segfaulting on Linux halfway through its run, so I ran it under Valgrind, expecting to be informed where the memory error occurred. Surprise! Not only did Valgrind not tell me what I needed to know, the test completed successfully. Huh?

Using old-fashioned binary searching, I tracked down the bug to an improper promotion of pointer to integer. Converting C pointers to integers is tricky business -- you have to make an intermediate cast to the integer type that is exactly the same byte size as the pointer type. Casting to a larger integer type doesn't necessarily work, even though intuitively it seems like it should because the larger type has enough room.

   /* On certain 32-bit Linux systems... */
   i64_t wrong        = pointer - another_pointer;
   i64_t still_wrong  = (i64_t)pointer - (i64_t)another_pointer;
   i64_t right        = (i64_t)(u32_t)pointer - (i64_t)(u32_t)another_pointer;

What I hadn't realized was that in addition to overriding malloc(), free(), and so on, Valgrind overrides the system's pointer-to-integer conversion routines. I hadn't even realized those routines were dynamic! The test completed correctly under Valgrind because it used the promotion algo the code was expecting. But Valgrind's behavior differed from the system's, so it was blind to the bug.

posted 2009-Jan-22 19:30 :: permalink

Copyright © 2004-2007 Marvin Humphrey