0

After getting my code to work, i looked if there were any memory leaks using valgrind. It found no memory leaks, however it returned these two errors:

==7109== Conditional jump or move depends on uninitialised value(s)
==7109==    at 0x4C32D08: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7109==    by 0x40138D: check (dictionary.c:154)
==7109==    by 0x400C39: main (speller.c:112)
==7109==  Uninitialised value was created by a heap allocation
==7109==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7109==    by 0x40119B: load (dictionary.c:88)
==7109==    by 0x400914: main (speller.c:40)

After searching online, I discovered the calloc method that initializes the pointer given by malloc to 0. After using it in my code, I got no more errors in valgrind, but i don't understand why? I don't understand what calloc() is doing that malloc() isn't. I understand that calloc does the same as malloc but initializes the memory block to 0.

Thanks in advance,

My code (load function):

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    // Initialize hash table
    for (int i = 0; i < N; i++)
    {
        hashtable[i] = NULL;
    }

    // Open dictionary
    FILE *file = fopen(dictionary, "r");
    if (file == NULL)
    {
        unload();
        return false;
    }

    // Buffer for a word
    char word[LENGTH + 1];

    // Insert words into hash table
    while (fscanf(file, "%s", word) != EOF)
    {
       // Create a node with the current word
       node *element = malloc(sizeof(node)); // allocate memory for a new node

       // Check if node was created sucessfully
       if (element == NULL)
       {
           printf("Error creating node\n");
           return false;
       }
       // Initialize current node
       add_word(element, word); // Adds the current dict word to the node
       element->next = NULL;

node structure:

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

add_word:

// Adds a word to a node's value (word)
int add_word(node *element, const char *word)
{
    if (element == NULL)
    {
        printf("Node is invalid");
        return 1;
    }

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

    // Success
    return 0;
}
3
  • What does your node structure look like? What does add_word do? Does it use the next member before you set it to NULL?
    – Blauelf
    Aug 30 '19 at 13:29
  • Sorry forgot to include those. I've edited my original quesiton Aug 30 '19 at 14:30
  • next obviously was the wrong thought by me, as strlen was involved (totally missed that). Should have guessed "missing null terminator" immediately. Thanks for adding the code, made it easier to see the mistake.
    – Blauelf
    Aug 30 '19 at 14:58
1

When you copy over the word into your node, you forget to write a null terminator. The byte likely is initially zero, so your programme will probably work, but there's no guarantee.

Using calloc would explicitly zero all the bytes, including the one later serving as null terminator, so this mistake would no longer cause valgrind to complain, it's just writing more zeroes than required.

BTW, there's a function that essentially does what your add_word does, and it writes a null terminator: strcpy.

1
  • You're right, totally forgot about the null char. Thank for your suggestion also! Aug 30 '19 at 14:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .