When testing with the small dictionary, it unloads as expected however when testing with the large dictionary, I receive the error "Could not unload dictionaries/large."

The only difference that I've noticed between the two dictionaries is amount of words in them. Having tested the small dictionary with varying words, including apostrophe's, multiple words with same bucket, all seems to work.

When the program checks if "(hashtable[25] == NULL)" for the large dictionary, the condition is not met but I can't seem to know figure out why.

My understanding of my code is as follows:

for each element in the hashtable
    have cursor point to the element in the hashtable
    while the cursor is null
        have a temporary pointer the location of cursor
        set cursor to the next location in the linked list
        free the node
if the the final element in the hashtable is NULL
    return true
    return false

// Unloads dictionary from memory, returning true if successful else false bool unload(void) { for (int i = 0; i < N; i++) { node *cursor = hashtable[i]; while (cursor != NULL) { node *temp = cursor; cursor = cursor->next; free(temp); } } if(hashtable[25] == NULL) { return true; } return false; }


Hehe, put the word "zebra" in your small dictionary and see if it still works! ;-)

I'm assuming that hashtable[25] represents words that start with 'z'. I'll wager that your small dictionary contains no words that start with z, or more precisely, no words that hash to 25.

Here's the problem. The free() function will release the memory pointed to by a pointer, but it does NOT set the pointer to NULL. So, the code as written will only return true if and only if no word is inserted into the hashtable[25] bucket.

There are two basic philosophies here. One is that the code is assumed to be nearly bulletproof and simply must release all the memory, so it always returns true. This code fits that bill. It starts with the first hash bucket, and walks through the linked list for that bucket, freeing every node until it gets to the end. Then it will rinse and repeat for every bucket that follows. It's nearly impossible to fail.

The second philosophy is to insert more robust code for checking for errors, such as the failure to free memory, etc. The choice is yours.

Neither philosophy will fix a memory leak in load(), so appropriate valgrind checking needs to be done to guarantee that the load code is solid.

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

  • Hah, you were spot on. Added "zebra" and it stopped working. Appreciate you pointing out that my code was not setting the pointer to NULL, once I addressed that, it was able to unload both small and large dictionaries. Great to hear the different approaches to performing the unload step. Much thanks!
    – bbeckca
    Jun 10 '19 at 6:14

You must log in to answer this question.

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