Contents
Memory Leaks with Valgrind
Let's move on to the file simple3.c to illustrate the usage of the open source software valgrind, which is freely available under GNU license. The distribution includes a memory error detector that is fast and easy to use.
After compilation we start the executable ./simple3 100 and receive the correct sum equal to 4950 and no error code.
Caveat with memory faults: Though there is a severe memory error within the code the program ends without faults and produces the correct output. Still the program is wrong but the error has no side effects like previous. But a small (correct) change, like introducing another printf statement or removing a comment, might change the side effect and lead to incorrect output or even a core dump. This makes memory errors so tricky!
Execution with support of valgrind reveals several memory errors:
valgrind ./simple3 100 ==54899== Memcheck, a memory error detector ==54899== Invalid write of size 4 ==54899== at 0x400698: main (simple3.c:13) ==54899== Address 0x5203068 is 0 bytes after a block of size 40 alloc'd ==54899== at 0x4C29BC3: malloc (vg_replace_malloc.c:299) ==54899== by 0x40065B: main (simple3.c:10) ==54899== ==54899== Invalid read of size 4 ==54899== at 0x4006B0: main (simple3.c:14) ==54899== Address 0x5203068 is 0 bytes after a block of size 40 alloc'd ==54899== at 0x4C29BC3: malloc (vg_replace_malloc.c:299) ==54899== by 0x40065B: main (simple3.c:10) ==54899== ==54899== HEAP SUMMARY: ==54899== in use at exit: 40 bytes in 1 blocks ==54899== total heap usage: 1 allocs, 0 frees, 40 bytes allocated ==54899== ==54899== LEAK SUMMARY: ==54899== definitely lost: 40 bytes in 1 blocks
First we find a leak of 40 bytes which comes from the comment in line 18 in front of free(squares). Let's fix this error. Execute the program and feel baffled. We have removed a comment in front of a correct function call and now the program gives the correct result but produces afterwards an error!
There are still other errors, as indicated by valgrind, in line 13 and line 14
and now these errors hit a sensitive piece of our code causing the program to
end with an error. Before switching to gdb again, we notice, that
valgrind complains, that
Address 0x5203068 is 0 bytes after a block of size 40 alloc'd.
In gdb we recall, that the first error occurs on line 13.
gdb ./simple3 (gdb) break 13 (gdb) run 100 13 squares[i]=i*1.0f; (gdb) print squares $1 = (float *) 0x602010 (gdb) watch *0x602038 (gdb) clear 13 (gdb) c Continuing. Hardware watchpoint 2: *0x602038 14 sum+=squares[i]; (gdb) print i $2 = 10 (gdb) print &squares[i] $3 = (float *) 0x602038 (gdb) quitFirst we set a breakpoint at the critical line 13. We notice that the line contains only one array starting at 0x602010. valgrind report something happened after a 40 byte block, so we watch 0x602038 which is 40 Bytes (in HEX 28) away. Line 13 is in a loop, so we clear the breakpoint and continue. The watchpoint is hit at i=10. Indeed only 10 elements for squares have been allocated and squares[10] is the first element at an invalid memory adress.
Now we recognize, that lines 10 and 11 should be interchanged to obtain a correct running program.