0

I'm currently at the CS50's pset5, and am working on the "Speller" problem. I managed to do all functions and don't have any compile or runtime errors. When using check50, though, I receive a sad face (:() on the last line, saying:

:( program is free of memory errors valgrind tests failed; see log for more information.

When I click on the link provided by check50, that's the output for the valgrind:

running valgrind --show-leak-kinds=all --xml=yes --xml-file=/tmp/tmph5epgoz9 -- ./speller substring/dict substring/text...
checking for output "MISSPELLED WORDS\n\nca\ncats\ncaterpill\ncaterpillars\n\nWORDS MISSPELLED: 4\nWORDS IN DICTIONARY: 2\nWORDS IN TEXT: 6\n"...
checking that program exited with status 0...
checking for valgrind errors...
168 bytes in 3 blocks are still reachable in loss record 1 of 1: (file: dictionary.c, line: 80)

Line 80 in my code is part of the load() function that I've completed. This is it:

node *new = malloc(sizeof(node)); // create a new last element in the linked list

Also, here's my full dictionary.c code:

// Implements a dictionary's functionality

#include <stdbool.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "dictionary.h"

int sz = -1;

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

// 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)
{
    // TODO
    int key = hash(word);
    node* curr = table[key];

    while (curr != NULL)
    {
        if (strcasecmp(word, curr->word) == 0)
        {
            return true;
        }
        curr = curr->next;
    }
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO
    return tolower(word[0]);
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    // TODO

    int isRoot[N];

    for (int i = 0; i < N; i++)
    {
        isRoot[i] = 1;
        table[i] = NULL;
    }

    FILE *f;
    if ((f = fopen(dictionary, "r")) == NULL)
    {
        return false;
    }

    char word[LENGTH+1];

    while (!feof(f)) // go through the whole dictionary file
    {
        fscanf(f, "%s", word);

        int key = hash(word); // hash the word

        node *new = malloc(sizeof(node)); // create a new last element in the linked list

        if (new == NULL) // check if malloc() worked properly
        {
            return false;
        }

        strcpy(new->word, word);

        // move the data into the new linked list element

        if (isRoot[key] == 1)
        {
            new->next = NULL;
            table[key] = new;
            isRoot[key] = 0;
        }
        else
        {
            new->next = table[key];
            table[key] = new;
        }

        sz++;
    }

    fclose(f);

    return true;
}

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

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    // TODO
    int i;

    for (i = 0; i < N; i++)
    {
        node* curr = table[i];
        while (curr != NULL)
        {
            node* tmp = curr;
            curr = curr->next;
            free(tmp);
        }
        if (curr != NULL)
        {
            return false;
        }
    }

    return true;
}

I firstly thought it might be from the unload() function, but looked up on several similar Stack Overflow questions and I had the exact algorithm for the unload() function (the right one). I don't know what I did wrong. Did I forget to free() memory somewhere? Doesn't my unload() function free all the memory I've allocated with malloc()?

Help would be appreciated. Thank you.

You must log in to answer this question.

Browse other questions tagged .