0

I'm working through ./speller in pset5, mainly the load() function. My function loads the dictionary without any issues, and Valgrind even shows no memory leaks. The problem is I have a ridiculous amount of errors and even though I've pinpointed where they seem to be coming from I don't know how to handle it. Here's the relevant code:

while(fscanf(dict, "%s", currentWord) == 1)
{
    // Get hash value of word
    tableIndex = hash(currentWord);

    // Initialize new node
    node* newNode = malloc(sizeof(node));
    newNode->word = malloc((strlen(currentWord) + 1) * sizeof(char));
    if (newNode == NULL || newNode->word == NULL)
    {
        printf("Error: Out of memory\n");
        return false;
    }

    // Copy word into new node
    strcpy(newNode->word, currentWord);
    newNode->next = NULL;

    // If no collision, hash word into head of list
    if (hashTable[tableIndex] == NULL)
        hashTable[tableIndex] = newNode;

    // Create a pointer and move down list 
    else
    {
        node* ptrNode = hashTable[tableIndex];

        while (ptrNode->next != NULL)
            ptrNode = ptrNode->next;

        // Append node to end of linked list
        ptrNode->next = newNode;
    } 

    // Increase dictionary size
    dictionary_size++;

    // Free word member before actual node
    free(newNode->word);
    free(newNode); 
}

// Close dictionary and return true
fclose(dict);
return true;

...close load()

And my Valgrind:

==32487== Invalid read of size 4
==32487==    at 0x8048989: load (my_new_test.c:120)
==32487==    by 0x804873D: main (my_new_test.c:53)
==32487==  Address 0x423b30c is 4 bytes inside a block of size 8 free'd
==32487==    at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-   linux.so)
==32487==    by 0x80489D3: load (my_new_test.c:132)
==32487==    by 0x804873D: main (my_new_test.c:53)
==32487== 
==32487== Invalid write of size 4
==32487==    at 0x80489AA: load (my_new_test.c:124)
==32487==    by 0x804873D: main (my_new_test.c:53)
==32487==  Address 0x423b30c is 4 bytes inside a block of size 8 free'd
==32487==    at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==32487==    by 0x80489D3: load (my_new_test.c:132)
==32487==    by 0x804873D: main (my_new_test.c:53)
==32487== 
==32487== Invalid read of size 4
==32487==    at 0x8048999: load (my_new_test.c:121)
==32487==    by 0x804873D: main (my_new_test.c:53)
==32487==  Address 0x423bb24 is 4 bytes inside a block of size 8 free'd
==32487==    at 0x402B3D8: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==32487==    by 0x80489D3: load (my_new_test.c:132)
==32487==    by 0x804873D: main (my_new_test.c:53)

==32487== HEAP SUMMARY:
==32487==     in use at exit: 0 bytes in 0 blocks
==32487==   total heap usage: 286,183 allocs, 286,183 frees, 2,584,308 bytes     allocated
==32487== 
==32487== All heap blocks were freed -- no leaks are possible
==32487== 
==32487== For counts of detected and suppressed errors, rerun with: -v
==32487== ERROR SUMMARY: 10000000 errors from 3 contexts (suppressed: 0 from  0)

I'm still a bit raw with Valgrind but from what I gather my issue seems to be inside the else statement, mainly the pointer created (node* ptrNode). Can anyone see something I'm not seeing? Any help would be greatly appreciated!

1

I think the main problem is that you're freeing new_node->word and new_node at the end of each iteration. here's a demonstration:

int *ptr0 = malloc(sizeof(int));
*ptr0 = 10; // stores 10 into the memory pointed to by ptr0

int *ptr1 = ptr0; // sets ptr1 to point to the same memory pointed to by ptr0

free(ptr0); /* frees the memory pointed to by ptr0 and ptr1
               free(ptr1) would do the same */
4
  • if i were to exclude the 2 calls to free at the end of each loop, what would happen at the beginning of the next iteration when I initialize a newNode? Does it malloc another chunk of memory for the second node? or does it use the same chunk? That's where I'm a little confused
    – jakewies
    Jun 14 '15 at 18:45
  • @jake_wies every call to malloc allocates a new chunk of memory, but that's what you want. you don't want to reuse the same chunk of memory because how do you expect all the nodes to get stored in one chunk of memory that is the size of a single node?
    – kzidane
    Jun 14 '15 at 18:54
  • i think i've gotten a little too 'free happy'. Not only this but if i'm freeing up the nodes in my load() function i won't be able to check the nodes in the check function because theyll be gone. I'm testing each function seperately and probably shouldnt look for a clean valgrind run until I'm done with the entire program lol
    – jakewies
    Jun 14 '15 at 19:11
  • @jake_wies you don't really have to wait to until you implement the whole program to solve the Invalid read/Invalid write errors. these errors are typically caused because you're trying to read from/write to from memory that it shouldn't read from/write to. see valgrind.org/docs/manual/mc-manual.html#mc-manual.badrw
    – kzidane
    Jun 14 '15 at 19:21

You must log in to answer this question.

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