Pinpointing "Conditional Jump or Move Depends on Uninitialized Value(S)" Valgrind Message

pinpointing conditional jump or move depends on uninitialized value(s) valgrind message

Use the valgrind option --track-origins=yes to have it track the origin of uninitialized values. This will make it slower and take more memory, but can be very helpful if you need to track down the origin of an uninitialized value.

Update: Regarding the point at which the uninitialized value is reported, the valgrind manual states:

It is important to understand that your program can copy around junk (uninitialised) data as much as it likes. Memcheck observes this and keeps track of the data, but does not complain. A complaint is issued only when your program attempts to make use of uninitialised data in a way that might affect your program's externally-visible behaviour.

From the Valgrind FAQ:

As for eager reporting of copies of uninitialised memory values, this has been suggested multiple times. Unfortunately, almost all programs legitimately copy uninitialised memory values around (because compilers pad structs to preserve alignment) and eager checking leads to hundreds of false positives. Therefore Memcheck does not support eager checking at this time.

Conditional jump or move depends on uninitialized value(s) with strcat in for loop

Using Valgrind to locate the problematic code

The "Conditional jump or move depends on uninitialised value(s)" message means Valgrind has determined that some result of your program depends on uninitialized memory.
Use the --track-origins=yes flag to track the origin of the uninitialized value. It might help you finding that value. From man 1 valgrind:

When set to yes, Memcheck keeps track of the origins of all uninitialised values. Then, when an uninitialised value error is reported, Memcheck will try to show the origin of the value. An origin can be one of the following four places: a heap block, a stack allocation, a client request, or miscellaneous other sources (eg, a call to brk).

More specifically in your program:

Problem 1: Using uninitialized genome

The line

char* genome = (char*) malloc(sizeof(char) * (genome_size+chr_total));

Allocates the genome buffer using malloc(2) and then consumes it in:

strcat(genome,data);

Please note that functions such as strlen(3) and strcat(3) works on C-strings, which are buffers that terminate with a null character ('\0').

malloc(2) just allocates memory and it doesn't initialize it so your allocated buffer may contain any value (and considered as uninitialized). You should avoid using string related functions with an uninitialized buffers as it results undefined behavior.

Fortunately calloc(2) does the trick - it allocates the buffer and initializes all of its bits to zero, resulting a valid 0 length C-string you can operate on. I suggest the following fix to ensure that genome is initialized:

char* genome = calloc(genome_size+chr_total+1, sizeof(char));

Also note that I've added +1 to the length of the allocated buffer. It is done to guarantee that the resulting genome will end with a null terminator (assuming that genome_size+chr_total is the total size of all the buffers returned from fai_fetch).

Also note that in terms of performance calloc is a bit slower than malloc (because it initializes the data) but for my opinion it is safer as it initializes the whole buffer. For the purposes of your specific program, you could save the performance burden by using malloc and initializing just the first byte:

char* genome = malloc(sizeof(char) * (genome_size + chr_total + 1));
if (NULL == genome) {
perror("malloc of genome failed");
exit(1);
}
// So it will be a valid 0 length c-string
genome[0] = 0;

We don't have to initialize the last byte to be 0 because strcat writes the terminating null character for us.

(Potential) Problem 2: Using potentially non-null terminated data with strcat

As you described in your question, the fai_fetch extracts some data:

const char *data = fai_fetch(seq_ref,chr_names[i],&chr_sizes[i]);

and then consumes it in the strcat line:

strcat(genome,data);

As I wrote above, because you use strcat, data should be null-terminated as well.

I'm not sure how fai_fetch is implemented but if it returns a valid C-string then you're all good.

If it doesn't then you should use strncat which works on buffers that are not null-terminated.

From man 3 strcat:

The strncat() function is similar, except that

  • it will use at most n bytes from src; and
  • src does not need to be null-terminated if it contains n or
    more bytes.

I suggest the following fix:

// I'm not sure what type `&chr_sizes[i]` is, assuming it's `size_t`
size_t length = &chr_sizes[i];
const char *data = fai_fetch(seq_ref,chr_names[i], length);
// Use strcat
strncat(genome, used_data, length);

Valgrind error: Conditional jump or move depends on uninitialised value

Ok your main problem is with null terminators, I dont understand a lot of you logic , I just called load with a simple 4 word file.

You must make sure that you make enough space for the null and you must make sure that you have a null.

so

the ones I found, you have to fix the others

char c;
while (fread(&c, sizeof(char), 1, dict))
{

if (c != '\n')
{
tmpWord[index] = c;
index++;
}
else
{
break;
}
}
tmpWord[index] = 0; <<<<===== add the null at the end

and

   //copy over the word into the node
// +1 for the null
strncpy(firstNode->word, tmpWord, index + 1);

now in hash

char* wordCopy = calloc(strlen(word)+1, sizeof(char));
strncpy(wordCopy, word, strlen(word)+1);

+1, +1

there are others I am sure.

The reason valgrind is complaining is becuase without the trailing null functions like strlen will keep readin memory till they do find a random null, valgrind sees you reading characters from waaaay off the end of what you copied

To make sure you have the null, put a printf or simply pause in the debugger and look at a string. If you see

 "cat"

things are good, but if you see

 "cat!!@*foodle!....ll"

then you know you have missed the null

Valgrind gives Conditional jump or move depends on uninitialised value(s) error

Although reading uninitialized memory through char* handle is not undefined behavior (and isn't via memcpy and memcmp functions), still it is considered good practice to always initialize memory before reading.

Valgrind properly diagnoses the "issue", you new_st = malloc(GET_STACK_SIZE(capacity, element_size)); allocate the memory and do not initialize the memory in the range ( offsetof(stack_t, _data), offsetof(stack_t, _data) + x * y ]. Then the code reads from it in memcpy(new_st, other, GET_STACK_SIZE(other->_capacity, other->_element_size)); and compares it in memcmp(st1, st2, - so valgrind shows uninitialized bytes errors.

The solve would be easy - initialize the memory. Either use calloc or call memset like memset(new_st.data, 0, x * y).

Valgrind: Conditional jump or move depends on uninitialised value(s). Is not terminating a string inside a longer array with '\0' enough?

key->word is not null terminated in the load function. The char array word is, though it's never populated.

Valgrind memcheck keeps dying before it finishes

Per the 5th comment from my original question, this appears to be related to the valgrind macros and can at least be worked around by spacing out the macro calls to give more processing time prior to the crash. Moving to a newer version might help, too, but is unknown and not an option for me at this time.



Related Topics



Leave a reply



Submit