Currently, I am totally struggling with APC's shm memory. Usually with most memory issues, the system cleanly segfaults. But when the memory is part of a 128 MB mmap() area, a couple of bytes here or there show up way too late in the debug operations to detect and fix.
Now, a lot of the allocator code has things which allocate n bytes + sizeof(header) and return the allocated area - sizeof(header). The problem is that my previous watchpoints code cannot differentiate between these two, unless I put an explicit watchpoint on the location. Not to mention, it has no concept of free operation in conjuction with the original block.
Digging around in valgrind code, I found an elegant answer to the problem - VALGRIND_MALLOCLIKE_BLOCK and VALGRIND_MAKE_NOACCESS. Here's a mocked up version of my code, which seems to work out.
#include <valgrind/valgrind.h> #include <valgrind/memcheck.h> void * alloc(size_t n) { void* x = malloc(n + 42); VALGRIND_MAKE_NOACCESS(x, n + 42); x = (unsigned char *)x + 42; VALGRIND_MALLOCLIKE_BLOCK(x, n, 0, 0); return x; } void dealloc(void * ptr) { free(ptr - 42); } int main() { size_t n = 200; char * a = alloc(n); a[0] = '1'; a[-1] = 'x'; VALGRIND_FREELIKE_BLOCK(a, n); dealloc(a); }
Now, the valgrind has red-zones, which are like canaries or sentinels for memory over-writes. I haven't figured out quite how to use them, but this should be enough right now, I think.
==28706== Invalid write of size 1 ==28706== at 0x80484ED: main (x.c:23) ==28706== Address 0x4025051 is 41 bytes inside a block of size 242 alloc'd
And the line 23 is the a[-1]. Valgrind is just amazing. Ever since I've hit up on this tool, I've found that my debugging life is a lot easier. Now, to reproduce original bug and nail that son of a b*tch :)
--They separate the right from the left, the man from the woman, the plant from the animal,
the sun from the moon. They only want to count to two.
-- Emma Bull, "Bone Dance