(original post was here)
Consider the following clearly buggy program:
#include <string.h>
int main()
{
char string1[10] = "123456789";
char *string2 = "123456789";
strcat(string1, string2);
}
and suppose to compile it:
gcc program.c -ggdb
and run valgrind on it:
valgrind --track-origins=yes --leak-check=yes --tool=memcheck --read-var-info=yes ./a.out
In the result, no error is shown:
==29739== Memcheck, a memory error detector
==29739== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==29739== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==29739== Command: ./a.out
==29739==
==29739==
==29739== HEAP SUMMARY:
==29739== in use at exit: 0 bytes in 0 blocks
==29739== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==29739==
==29739== All heap blocks were freed -- no leaks are possible
==29739==
==29739== For counts of detected and suppressed errors, rerun with: -v
==29739== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
What am I missing?
If you compile your program with the -g flag, Valgrind will show you the function names and line numbers where errors occur. Sometimes the actual bug occurs on a different line (particularly for uninitialized value errors) but the line number Valgrind tells you is a good starting point.
Valgrind prints this warning when an unusually large memory region is allocated, on suspicion that the size may be so large due to an error. If the intention of your code was to allocate a large block, then all is well.
For example, valgrind ./myprog might produce the following summary: LEAK SUMMARY: definitely lost: 48 bytes in 1 blocks indirectly lost: 24 bytes in 3 blocks possibly lost: 0 bytes in 0 blocks still reachable: 14 bytes in 1 blocks suppressed: 0 bytes in 0 blocks.
Yes, there are false positives with Valgrind, that's why it has suppression files for particular glibc and gcc versions, for example.
It did not report anything wrong because you were using memcheck
, which does not perform check on global or stack arrays, it only perform bounds checks and use-after-free checks for heap arrays. So in this case, you can use valgrind SGCheck to check stack arrays:
valgrind --tool=exp-sgcheck ./a.out
It indeed report the error for me.
For more information, refer the sgcheck docs:
http://valgrind.org/docs/manual/sg-manual.html
adding the log:
$ valgrind --tool=exp-sgcheck ./a.out
==10485== exp-sgcheck, a stack and global array overrun detector
==10485== NOTE: This is an Experimental-Class Valgrind Tool
==10485== Copyright (C) 2003-2015, and GNU GPL'd, by OpenWorks Ltd et al.
==10485== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==10485== Command: ./a.out
==10485==
==10485== Invalid read of size 1
==10485== at 0x4C2A374: strlen (h_intercepts.c:131)
==10485== by 0x4E9DD5B: puts (in /usr/lib64/libc-2.22.so)
==10485== by 0x4005C8: main (v.c:11)
==10485== Address 0xfff00042a expected vs actual:
==10485== Expected: stack array "string1" of size 10 in frame 2 back from here
==10485== Actual: unknown
==10485== Actual: is 0 after Expected
==10485==
==10485== Invalid read of size 1
==10485== at 0x4EA9BA2: _IO_default_xsputn (in /usr/lib64/libc-2.22.so)
==10485== by 0x4EA7816: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.22.so)
==10485== by 0x4E9DDF7: puts (in /usr/lib64/libc-2.22.so)
==10485== by 0x4005C8: main (v.c:11)
==10485== Address 0xfff00042a expected vs actual:
==10485== Expected: stack array "string1" of size 10 in frame 3 back from here
==10485== Actual: unknown
==10485== Actual: is 0 after Expected
==10485==
123456789123456789
==10485==
==10485== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With