I've grinding away at this one problem for a couple of days now, and can't quite work out what's going wrong. My code passes check50. The output is fine. I'm relatively happy with how quickly it runs.
I can't however, manage to free 1 remaining 568 byte block of memory.
Here is what valgrind says:
==13511==
==13511== HEAP SUMMARY:
==13511== in use at exit: 568 bytes in 1 blocks
==13511== total heap usage: 143,093 allocs, 143,092 frees, 8,014,232 bytes allocated
==13511==
==13511== 568 bytes in 1 blocks are still reachable in loss record 1 of 1
==13511== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13511== by 0x4EA537C: __fopen_internal (iofopen.c:73)
==13511== by 0x40132E: load (dictionary.c:99)
==13511== by 0x400A0D: main (speller.c:45)
==13511==
==13511== LEAK SUMMARY:
==13511== definitely lost: 0 bytes in 0 blocks
==13511== indirectly lost: 0 bytes in 0 blocks
==13511== possibly lost: 0 bytes in 0 blocks
==13511== still reachable: 568 bytes in 1 blocks
==13511== suppressed: 0 bytes in 0 blocks
==13511==
==13511== For counts of detected and suppressed errors, rerun with: -v
==13511== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Here's my load function:
bool load(const char* dictionary)
{
// open dictionary from file
FILE* dicptr = fopen(dictionary,"r");
if (dicptr == NULL)
{
printf("Couldn't open dictionary.\n");
return false;
}
// set all node pointers in hashTable array to NULL
for (int i = 0; i < HASH_TABLE_SIZE; i ++)
{
hashTable[i] = NULL;
}
// loop until end of end of dictionary file
while(!feof(dicptr))
{
// create pointer to node on the heap and set its 'next' pointer to NULL
node* newNode = malloc(sizeof(node));
newNode->next = NULL;
// load string from dictionary into newNode->word and check for end of dictionary file
if (fscanf(dicptr, "%s", newNode->dicWord) != 1)
{
// if end of dictionary file, free newNode and return true
free(newNode);
return true;
}
// store index returned from hash function as int
int hashIndex = hashFunction(newNode->dicWord);
// set hashTable[hashIndex] to newNode if that array entry is null
if (hashTable[hashIndex] == NULL)
{
hashTable[hashIndex] = newNode;
}
// else set next pointer to previous head of linked list and make newNode the new head of the list
else
{
node* head = hashTable[hashIndex];
newNode->next = head;
head = newNode;
hashTable[hashIndex] = head;
}
// update dictionary word count
wordCount ++;
}
return true;
}
And here's my unload function:
bool unload(void)
{
for (int i = 0; i < HASH_TABLE_SIZE; i ++)
{
// initialise a new node pointer that will traverse the list and set it to index 'i' of hash table
node* trav = hashTable[i];
// traverse through list freeing nodes until reaching a null pointer
while (trav != NULL)
{
node* temp = trav;
trav = trav->next;
free(temp);
}
// ensure that index 'i' of the hash table is set to null
hashTable[i] = NULL;
}
return true;
}
According to valgrind, my load function is allocating 2 more blocks of memory than there are words in the dictionary.
I can understand 1 of those - the code allocates memory for a new node before checking if it has reached the end of the dictionary file, but I then subsequently free that memory block. So where is this other block being created and how do I free it? It's driving me insane.
A huge thank you to anyone that can help!