Search code examples
cmallochashtablevalgrind

Uninitialized value was created by a heap allocation


I'm trying to implement a dictionary of words using a hash table, so I need to have it global, and in one of my header files I declare it

extern node** dictionary;

Where node is

typedef struct node
{
    char* word;
    struct node* next;
} node;

Then in another file in which functions are defined I include the header which has the dictionary declaration, and also I add at the top

node** dictionary;

Then in the function which actually loads the dictionary I first allocate memory for the linked lists which will make the hash table

bool load(const char* dict_file)
{
    dictionary = malloc(sizeof(node*) * LISTS);

    FILE* dict = fopen(dict_file, "r");

    if(dict == NULL)
        return false;

    char buffer[MAX_LEN + 2];

    size_dict = 0;

    while(fgets(buffer, MAX_LEN + 2, dict) != NULL)
    {
        node* new_node = malloc(sizeof(node));

        int len = strlen(buffer);

        new_node->word = malloc(sizeof(char) * (len));

        //avoid \n
        for(int i = 0; i < len - 1; i++)
            new_node->word[i] = buffer[i];

        new_node->word[len - 1] = '\0';

        new_node->next = NULL;

        int index = hash(buffer);

        new_node->next = dictionary[index];

        dictionary[index] = new_node;

        size_dict++;
    }

    if (ferror(dict))
    {
        fclose(dict);
        return false;
    }

    fclose(dict);
    return true;
}

So the program works fine, I then free all the allocated memory for strings and nodes and when I run valgrind(a debugger which detects memory leaks) it says no memory leaks are possible, but it says that there is an error Uninitilised value was created by a heap allocation and redirects me to that exact line where I'm allocating memory for dictionary the exact first line of the load function which I've written above.
What am I doing wrong? I guess the way I use dictionary globally is wrong, so can anybody suggest some other way of keeping it global and avoid this error?


Solution

  • In the updated code you use an uninitialized pointer:

    dictionary = malloc(sizeof(node*) * LISTS);
    
    // .... code that does not change dictionary[i] for any i
    
    new_node->next = dictionary[index];   // use uninitialized pointer
    

    As people had wrote already, this will only work if you had pre-set all the pointers to be NULL before entering this loop:

    dictionary = malloc(sizeof(node*) * LISTS);
    if ( !dictionary ) {
        return false;
    }
    
    for (size_t i = 0; i < LISTS; ++i) {
        dictionary[i] = NULL;
    }