Home > OS >  How to resolve error displayed by Valgrind "Conditional jump or move depends on uninitialised v
How to resolve error displayed by Valgrind "Conditional jump or move depends on uninitialised v

Time:09-19

I am writing program in C to load dictionary and then check provided file for misspellings. Function to load dictionary uses hash bucket and chaining rule to resolve collisions. Chains are made from linked lists:

#define LENGTH 45

    typedef struct node
{
    char word[LENGTH   1];
    struct node *next;
}
node;

Everything is working perfectly, except when I check the code with Valgrind. There is no memory leaks, but there seems to be error in using uninitialized value:

Conditional jump or move depends on uninitialised value(s)
    by 0x109B8F: load (dictionary.c:111)
    by 0x10929B: main (speller.c:40)
  Uninitialised value was created by a heap allocation
    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
    by 0x109B21: load (dictionary.c:96)
    by 0x10929B: main (speller.c:40)

I repeatedly debugged code narrowing down source of this error to my function responsible for loading dictionary to heap. To be more exact problem seem to be in creating temporary pointer for new node and then trying to access word variable inside node even when the word is copied from another char table and initialized:

node *temp = malloc(sizeof(node)); // Error source (line 96)

if (temp == NULL)
{
   return false;
}

temp->next = NULL;

for (int i = 0; word_buffer[i] != '\0'; i  )
{
    temp->word[i] = word_buffer[i];
}

int key = hash(temp->word); // Error in using temp->word, not initialised (line 111)

How can I change these lines of code to resolve Valgrind error?
Can you explains source of this error? I only recently started my programming journey and want to know to avoid this error in future

Here is Minimal, Reproducible Example

#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>

#define LENGTH 45

// Represents a node in a hash table
typedef struct node
{
    char word[LENGTH   1];
    struct node *next;
}
node;


int main(void)
{
    char word_buffer[LENGTH   1] = {'C', 'A', 'T'};

    node *temp = malloc(sizeof(node)); // Error source

    if (temp == NULL)
    {
        return 1;
    }

    temp->next = NULL;

    for (int i = 0; word_buffer[i] != '\0'; i  )
    {
        temp->word[i] = word_buffer[i];
    }

    if (temp->word[0] == '\0') // Error in using temp->word, not initialised
    {
        return 2;
    }

    printf("%s\n", temp->word);

    free(temp);
    
    return 0;
}

CodePudding user response:

The code shown fails to add a null terminator to temp->word. Supposing that hash expects to receive a null-terminated string, the lack of a null terminator would cause hash to read uninitialized elements in temp->word.

This could be fixed by changing:

for (int i = 0; word_buffer[i] != '\0'; i  )
{
    temp->word[i] = word_buffer[i];
}

to:

int i;
for (i = 0; word_buffer[i] != '\0'; i  )
{
    temp->word[i] = word_buffer[i];
}
temp->word[i] = '\0';

although it should be noted the code shown has no guard against exceeding the length of temp->word array.

  • Related