Michael Schäfer
Michael Schäfer

Reputation: 57

why does valgrind detect uninitialised values only so late

I want to understand the valgrind log messages and use the following code

#include <iostream>

int main()
{
 int numbers[] = {1,2,3,4,5,6,7,8,9,10};
 int length = sizeof(numbers) / sizeof(numbers[0]);
 std::cout << "length: " << length << std::endl;
 for (int i = 0; i < length + 10; ++i)
 {
     int number = numbers[i];
     if (number > 5)
     {
         std::cout << number << " is greater than 5" << std::endl;
     } else {
         std::cout << number << " is less or equal 5" << std::endl;
     }

 }

}

to produce uninitialised values. If I run the program in valgrind I don't receive a corresponding message. If I run the for-loop to length + 10 valgrind detects uninitialised values.

Why does valgrind detect the unitialised values only so late?

==2484== Conditional jump or move depends on uninitialised value(s)
==2484==    at 0x108A3C: main (arrays.cpp:11)
==2484==  Uninitialised value was created by a stack allocation
==2484==    at 0x51E6ABB: (below main) (libc-start.c:137)
==2484== 
==2484== Conditional jump or move depends on uninitialised value(s)
==2484==    at 0x4F43C0A: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484==    by 0x4F501A4: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484==    by 0x108A85: main (arrays.cpp:15)
==2484==  Uninitialised value was created by a stack allocation
==2484==    at 0x51E6ABB: (below main) (libc-start.c:137)
==2484== 
==2484== Use of uninitialised value of size 8
==2484==    at 0x4F4370E: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484==    by 0x4F43C33: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484==    by 0x4F501A4: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484==    by 0x108A85: main (arrays.cpp:15)
==2484==  Uninitialised value was created by a stack allocation
==2484==    at 0x51E6ABB: (below main) (libc-start.c:137)
==2484== 
==2484== Conditional jump or move depends on uninitialised value(s)
==2484==    at 0x4F4371B: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484==    by 0x4F43C33: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484==    by 0x4F501A4: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484==    by 0x108A85: main (arrays.cpp:15)
==2484==  Uninitialised value was created by a stack allocation
==2484==    at 0x51E6ABB: (below main) (libc-start.c:137)
==2484== 
==2484== Conditional jump or move depends on uninitialised value(s)
==2484==    at 0x4F43C66: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484==    by 0x4F501A4: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25)
==2484==    by 0x108A85: main (arrays.cpp:15)
==2484==  Uninitialised value was created by a stack allocation
==2484==    at 0x51E6ABB: (below main) (libc-start.c:137)

EDIT: I changed the code. THis is the whole code i used. compile: g++ -c -g3 arrays.cpp arrays.cpp valgrind: valgrind --tool=memcheck --track-origins=yes --num-callers=100 --log-file=uv_log.txt ./arrays

EDIT 2:

length: 10
1 is less or equal 5
2 is less or equal 5
3 is less or equal 5
4 is less or equal 5
5 is less or equal 5
6 is greater than 5
7 is greater than 5
8 is greater than 5
9 is greater than 5
10 is greater than 5
-882498304 is less or equal 5
-188984184 is less or equal 5
1084208 is greater than 5
0 is less or equal 5
85879703 is greater than 5
0 is less or equal 5
0 is less or equal 5

Upvotes: 0

Views: 171

Answers (1)

geza
geza

Reputation: 29990

You don't actually check for uninitialized access. You check for index out of bounds access. In your case, the out of bounds access is on the stack, so you access some memory, which is on the stack. And you're lucky, because the whole accessed area is on the stack, so you don't get an invalid read. Your program reads some data of the stack, which happens to be initialized for the length+1 case (because there is some other thing written to it, for example, it can be function parameter, other local variable or the function's return address), so valgrind is not able to report any error.

But for the length+10 case, it is large enough to actually read from some uninitialized memory. And I bet, if you increase 10 to a much larger number, you'll get invalid read (which causes segmentation fault).

Upvotes: 1

Related Questions