Search code examples
cmalloccs50coredump

CS50: my malloc statement initially works but shows an error after several iterations of a loop. Why is this happening?


I am trying to solve this CS50 problem using the djb2 hashing algorithm: https://cs50.harvard.edu/x/2024/psets/5/speller/. Please see my code below. Other files needed to run the code can be found in the CS50 link provided above. I have only made changes to dictionary.c which is included in the code below.

// Implements a dictionary's functionality

#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "dictionary.h"

// 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 = 100;

//Variable to count number of words loaded into dictionary
int count = 0;

// Hash table
node *table[N];

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    // TODO
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO: Improve this hash function
    unsigned long hash = 5381;
    int c;
    while((c = *word++))
    {
        hash = (((hash << 5) + hash) + c);
    }
    int hash_value = hash % N;
    return hash_value;
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    // TODO
    FILE *dict_file = fopen(dictionary, "r");
    if (dict_file == NULL)
    {
        printf("Could not open %s.\n", dictionary);
        return false;
    }
    for(int i = 0; i < N; i++)
    {
        table[i] = NULL;
    }
    char c;
    int i = 0;
    node *new_node = malloc(sizeof(node));
    while (fread(&c, sizeof(char), 1, dict_file))
    {
        // printf("%c", c);
        if(c != '\n')
        {
            new_node -> word[i] = c;
            i++;
        }
        else
        {
            int key = hash(new_node -> word);
            new_node -> next = table[key];
            table[key] = new_node;
            // printf("%lu", sizeof(node));
            new_node = malloc(sizeof(node));
            count++;
        }
    }
    fclose(dict_file);
    if(count > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

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

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

Error I am seeing- malloc(): corrupted top size Aborted (core dumped)

Based on what I've read online, I think a corrupted top size issue means that the size provided as an argument within the malloc call is invalid. My malloc call is located within the bool load function where I am loading words from the dictionary file into a hash table using a djb2 hashing algorithm. My function loops over each character in the file until a word is formed and assigned to a node in the hash table after which I call malloc to assign a space equal to the size of a node for storing the next word.

I used debugging tools and print statements to figure out that this function worked as expected while loading the first ten words in the dictionary (until aardwolf) but shows the error described above when malloc is called after aardwolf is saved in the hash table. The size of the node is a constant (56) so I am confused about why this size is suddenly invalid for malloc. Any thoughts on why this might be happening?


Solution

  • The problem is i in load. It is initialized before the while loop. It is incremented for every character read (not just the chars in each word).