CS50 2024 Speller memory leak

52 Views Asked by At

I am currently taking CS50 and working on the Speller questions. I am able to get the code to work but the program fails the valgrind test on check50.

Valgrind tells me the leak of 56bytes is at line 86 where I declared a malloc to store the words as the program scans through the dictionary.

I tried doing a fclose at the end of the while loop but it messes up the code.

==75771== HEAP SUMMARY:
==75771==     in use at exit: 7,703,248 bytes in 137,558 blocks
==75771==   total heap usage: 143,096 allocs, 5,538 frees, 8,023,256 bytes allocated
==75771== 
==75771== 7,703,248 bytes in 137,558 blocks are still reachable in loss record 1 of 1
==75771==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==75771==    by 0x109A93: load (dictionary.c:86)
==75771==    by 0x1092DB: main (speller.c:40)
==75771== 
==75771== LEAK SUMMARY:
==75771==    definitely lost: 0 bytes in 0 blocks
==75771==    indirectly lost: 0 bytes in 0 blocks
==75771==      possibly lost: 0 bytes in 0 blocks
==75771==    still reachable: 7,703,248 bytes in 137,558 blocks
==75771==         suppressed: 0 bytes in 0 blocks
==75771== 
==75771== For lists of detected and suppressed errors, rerun with: -s
==75771== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
// Implements a dictionary's functionality
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>

#include "dictionary.h"

//Declare variables
int word_count;
unsigned int hash_value;

// Represents a node in a hash table
typedef struct node
{
    char word[LENGTH + 1];
    struct node *next;
} node;

// TODO: Choose number of buckets in hash table
const unsigned int N = 26;

// Hash table
node *table[N];

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    //Obtain hash value of word
    hash_value = hash(word);

    //Declare cursor variable
    node *cursor = table[hash_value];

    while (cursor != 0)
    {
        //Return true if match found
        if (strcasecmp(word, cursor->word) == 0)
        {
            return true;
        }
        //Move cursor to next node if no match found
        cursor = cursor->next;
    }
    //Return false if no match after traversing thus misspelt word
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    long sum = 0;
    int hash;

    //Division hash
    for (int i=0; i<strlen(word); i++)
    {
        sum += tolower(word[i]);
    }
    hash = sum % N;

    return hash;
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    //Open dictionary using fopen r
    FILE *source = fopen(dictionary, "r");

    if (source == NULL)
    {
        printf("Error in opening file %s\n", dictionary);
        return false;
    }

    //Declare word variable to store word while scanning
    char word[LENGTH + 1];

    //Loop to scan for word until fscanf returns EOF
    while (fscanf(source, "%s", word) != EOF)
    {
        //Allocate memory for word node
        node *word_node = malloc(sizeof(node));

        if (word_node == NULL)
        {
            return false;
        }

        //Copy word from source into node
        strcpy(word_node->word, word);

        //Obtain hash value for word
        hash_value = hash(word);

        //Insert word into respective hash table
        word_node->next = table[hash_value];
        table[hash_value] = word_node;

        word_count++;
    }

    //Close file
    fclose(source);
    return true;
}

// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
    if (word_count > 0)
    {
        return word_count;
    }
    else
    {
        return 0;
    }
}

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    //Loop through buckets
    for (int i = 0; i < N; i++)
    {
        //point cursor to first table
        node *cursor = table[i];

        //move cursor until it reaches the end
        while (cursor != NULL)
        {
            //create unloader for current cursor position
            node *unloader = cursor;

            //move cursor to next node
            cursor = cursor->next;

            //free memory from current node using unloader
            free(unloader);
        }
        return true;
    }
    return false;
}
0

There are 0 best solutions below