Gagan karanth
Gagan karanth

Reputation: 109

Pset5 Speller: I'm getting segmentation fault with small dictionary

When i used check50, my program was not giving any report as output. So i tried my code with small dictionary and i got a segmentation fault. I think it has do with my unload function This is my code

// Implements a dictionary's functionality

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

#include "dictionary.h"

// 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 = 125;
int word_size = 0;

// Hash table
node *hashtable[N];

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    //Convert the word to lowercase
    int length = strlen(word);
    char copy[length + 1];
    for (int i = 0; i < length; i++)
    {
        copy[i] = tolower(word[i]);
    }
    copy[length] = '\0';
    //Find out the hash value
    int hash_value = hash(copy);
    node *tmp = hashtable[hash_value];
    //Check if word is in dictionary
    while(tmp != NULL)
    {
        if(strcasecmp(tmp->word, copy) == 0)
        {
            return true;
        }
        tmp = tmp->next;
    }
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    //It's djb2 hash function
    unsigned int hash = 5381;
    int c;
    while ((c = *word++))
        hash = ((hash << 5) + hash) + c;
    return hash % N;
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    //Initialize all indexs of hastable to NULL
    for(int i =0; i < LENGTH + 1; i++)
    {
        hashtable[i] = NULL;
    }
    char word[LENGTH +1];
    int pos;
    FILE *dict = fopen(dictionary,"r");
    if(dict == NULL)
    {
        return false;
    }
    //Scan every word...I think my problem is in here
    while (fscanf(dict, "%s", word) != EOF)
    {
        word_size++;
        int length = strlen(word);
        char copy[length + 1];
        for (int i = 0; i < length; i++)
        {
            copy[i] = tolower(word[i]);
        }
        copy[length] = '\0';
        node *new_node = malloc(sizeof(node));
        strcpy(new_node->word,copy);
        new_node->next = NULL;
        //Find the hash value
        pos = hash(copy);
        //Set the pointer of the new node to index of hashtable
        new_node->next = hashtable[pos];
        hashtable[pos] = new_node;
    }
    return true;
}

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

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

Can anyone say the write logic if my unload function is wrong. It works fine with large dictionary. I tried but couldn't figure out how to use debug50

Upvotes: 0

Views: 115

Answers (1)

Roberto Caboni
Roberto Caboni

Reputation: 7490

In your unload () function you soon define

node *cursor = NULL;

but then, without assigning to cursor any other value, you dereference it:

while ( cursor->next != NULL )

Dereferencing a NULL pointer raises undefined behavior, and it will likely result in a segmentation fault.

The following action is free(cursor); that, with a NULL pointer, is not good as well.

Upvotes: 1

Related Questions