It took me two hours to find out that I hadn't properly initialized a dynamic array that was allocated on the stack. Valgrind is truly an awesome tool, and in conjuction with GDB it is really powerful. I will have probably forgotten how to use Valgrind in a week from now, so that's why I'm writing this quick summary on how I managed to debug the issue. I hope it's useful for future reference.
In a shell, start the program in the Valgrind VM:
valgrind --vgdb=yes --vgdb-error=0 ./my_program
in another shell, start gdb
and attach it to vgdb:
gdb ./my_program
(gdb) target remote | vgdb
(gdb) c
Then, the program runs and eventually hits an error:
==231851== Conditional jump or move depends on uninitialised value(s)
==231851== at 0x10B6C8: lane_kmeans_segment (lane_kmeans.c:42)
==231851== by 0x1093D7: main (lane_kmseg_test.c:32)
==231851==
==231851== (action on error) vgdb me ...
in GDB terminal this shows:
Program received signal SIGTRAP, Trace/breakpoint trap.
0x000000000010b6c8 in lane_kmeans_segment (image=0x4b816e0, iterations=10 '\n', clusters=2 '\002') at ./src/lane_kmeans.c:42
42 if (diff < pixels[k].nearest) {
First, get a pointer to the element that may be uninitialized. And also get the size of the element (in bytes).
(gdb) p &diff
$46 = (int *) 0x1ffefff9cc
(gdb) p sizeof(diff)
$47 = 4
Then, investigate whether it is allocated or not (ff
means a byte is NOT allocated, 0
means a byte IS allocated):
(gdb) monitor xb 0x1ffefff9cc 4
ff ff ff ff
0x1FFEFFF9CC: 0x10 0x00 0x00 0x00
So, we found our uninitialized memory.
To fix it, just assign = 0
to variables and = {0}
to arrays when initializing them.
Or use memset
.
Use the following GDB commands to exit:
(gdb) monitor v.kill
(gdb) q
Either static initializers or memset
is OK.
int diff = 0, avg[k] = {0}, total[k];
memset(total, 0, sizeof(total));