-1

I have been trying many different things to figure out the error:

==14541== Conditional jump or move depends on uninitialised value(s)                  
==14541==    at 0x4011AC: main (so4.c:15)            

line 15 is a conditional test. Example code:

#include <stdio.h>

int main(void)
{
   int numbers[4];
   numbers[0] = 1;
   numbers[1] = 3;
   numbers[2] = 4;
   int num = 0;
   for(int i = 0; i < 4; i++)
   {
    num *= 10;
    num += numbers[i];
   }
   if (num)
   {
      printf("num %d\n", num);
   }
}

For context the numbers is an array that holds a number and I am trying to combine them so {1,3,4} should result in 134.

The conditional test is where it gives the Valgrind error

usersman
  • 23
  • 5
  • 2
    Have you initialized value of numbers[i]? If not num also may have some garbage value which causes issue in while(num--) – Sreeraj Chundayil Sep 08 '21 at 03:49
  • 1
    Post a [mcve] please. – Nate Eldredge Sep 08 '21 at 04:04
  • 3
    If the array contains only 3 elements `{1, 3, 4}`, but you loop up to `i < 4`, you'll access an uninitialized element of the array and cause this error. – Barmar Sep 08 '21 at 04:13
  • Not sure what it takes to reopen such a question. Desired behaviour is there. MRE is there. Error output is there. – Paul Floyd Sep 16 '21 at 14:46
  • @PaulFloyd: The better close reason of the question would be a duplicate of some question about local variable initialization, like [that one](https://stackoverflow.com/questions/1597405/what-happens-to-a-declared-uninitialized-variable-in-c-does-it-have-a-value). But on Stack Overflow we tend to not reopen questions just for change the close reason. – Tsyvarev Sep 23 '21 at 21:29
  • Somebody please create an answer. Even you usersman or @Barmar. Or close for dupe... though I am unhappy with the one proposed by Tsyvarev – Yunnosch Sep 24 '21 at 07:34
  • @Tsyvarev the answer that you link to looks correct, but a) does not mention memcheck and b) doesn't explain the transitive nature of undefinedness that memcheck is tracking. There may be duplicates (possibly in one of my own answers) but I didn't see anything with a quick search. I expect that the OP will have moved on by now. – Paul Floyd Sep 24 '21 at 08:00
  • Does this answer your question? [pinpointing "conditional jump or move depends on uninitialized value(s)" valgrind message](https://stackoverflow.com/questions/2612447/pinpointing-conditional-jump-or-move-depends-on-uninitialized-values-valgrin) – Tsyvarev Sep 24 '21 at 09:32
  • Yes. The update in that post is describes what I'm talking about. – Paul Floyd Sep 24 '21 at 09:54

1 Answers1

1

Let's go through the code step by step (imagine that each line below is a "next" command in a debugger), with comments as to what memcheck is doing. The for loop has been unwound and I've put two lines for each statement executed within the for statement.

int numbers[4]; // 16 bytes reserved on the stack, recorded as uninitialized
numbers[0] = 1; // the first 12 bytes of the stack area get values stored
numbers[1] = 3; // in them and recorded as initialized
numbers[2] = 4;
// bytes 12 to 15 on the stack are still uninitialized
int num=0; // num initialized to zero
for(int i = 0; i < 4; i++) // initialize i to 0
for(int i = 0; i < 4; i++) // check i < 4, initialized
num *= 10; // multiply num by 10 (0), initialized
num += numbers[i]; // add numbers[0] (1) to num (1), initialized
for(int i = 0; i < 4; i++) // increment i (1), initialized
for(int i = 0; i < 4; i++) // second loop, check i < 4, initialized
num *= 10; // multiply num by 10 (10), initialized
num += numbers[i]; // add numbers[1] (3) to num (13), initialized
for(int i = 0; i < 4; i++) // increment i (2), initialized
for(int i = 0; i < 4; i++) // third loop, check i < 4, initialized
num *= 10; // multiply num by 10 (130), initialized
num += numbers[i]; // add numbers[2] (4) to num (134), initialized
for(int i = 0; i < 4; i++) // increment i(3), initialized
for(int i = 0; i < 4; i++) // fourth loop, check i < 4, initialized
num *= 10; // multiply num by 10 (1340), initialized
num += numbers[i]; // add numbers[3] (????) to num (????), uninitialized, see below
if (num) // read num and use it in a condition, print an error message

There are two important events.

num += numbers[3]

numbers[3] is uninitialized. Adding it to num causes num to be marked as uninitialized even though it was previously marked as initialized. However, no error message is generated at this point. Copying uninitialized data is very common and is often harmless. If memcheck produced error messages for every such copy it would produce an unworkably large amount of error messages. memcheck does not have a crystal ball and so it cannot tell in advance whether copied uninitialized data will be used in an unsafe way.

if (num)

Here the code is making some decision based on num, which is flagged as uninitialized. This is unsafe, so Valgrind generates an error.

This is what the manual is says as described in the link in the comment from @Tsyvarev above, but I've tried to spell it out concretely.

Paul Floyd
  • 5,530
  • 5
  • 29
  • 43