0

I worked on the speller code for bath 2020 for cs50x course.

My code passed all test cases but got stuck at a valgrind error.

Im new to this and Im unable to comprehend valgrind logs.

Please help understand where am I going wrong and give me a direction to resolve my errors

// Implements a dictionary's functionality
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>


#include <stdbool.h>

#include "dictionary.h"

int debuglevel = 2;

// 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)
{
    node *head = table[hash(word)];
    node *cursor = head;
    while (cursor != NULL)
    {
        if (strcasecmp(word, cursor->word) == 0)
        {
            //printf("Found the matching word in dictionary at hashbucket: %d, word is: %s, dictionary word is: %s, cursor is pointing to: %p\n", hash(word), word, cursor->word, cursor);
            return true;
        }

        if (debuglevel > 4)
        {
            printf("Trying to match word [%s] in dictionary word: [%s] in hashbucket: [%d], cursor is pointing to: %p\n", word, cursor->word,
                   hash(word), cursor);    
        }
        cursor = cursor->next;
    }


    // TODO
    return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
    int code = word[0] < 97 ? word[0] + 32 - 97 : word[0] - 97;
    // TODO
    return code;
}


node *front(node *head, char word[LENGTH + 1])
{
    node *p;
    p = malloc(sizeof(node));
    strncpy(p->word, word, strlen(word) - 1);
    p->next = head;
    return (p);
}


int count = 0;

int hashbucket;


// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    FILE *fp;
    char *line = NULL;
    size_t len = 0;
    ssize_t read;
    node *tmp1 = malloc(sizeof(node));

    for (int i = 0; i < 26; i++)
    {
        table[i] = malloc(sizeof(node));
        table[i]->next = NULL;
    }

    fp = fopen(dictionary, "r");
    if (fp == NULL)
    {
        printf("Couldn't open file [dictionaries/large] to read\n");
        return false;
    }

    while ((read = getline(&line, &len, fp)) != -1)
    {
        hashbucket = line[0] < 97 ? line[0] + 32 - 97 : line[0] - 97;
        // printf("populating hashbucket: [%d] with [%s] of length: [./speller texts/lalaland.txt%zd]\n", hashbucket, line, read);
        //       node *tmp = malloc(sizeof(node));                        //create a tmp node and populate it with this new word in >>line<<
        //       strcpy(tmp->word, line);

        table[hashbucket] = front(table[hashbucket], line);
    }
    fclose(fp);

    for (int i = 0; i < 26; i++)
    {
        tmp1 = table[i];
        // printf("Printing contents of table[%d]\n", i);

        while (tmp1->next != NULL)
        {
            // printf("word from linked list is [%s] with address of struct: [%p] and address of tmp1->word: [%p] and address of tmp1->next: [%p]\n", tmp1->word, tmp1, tmp1->word, tmp1->next);
            tmp1 = tmp1->next;
            count++;
        }

    }
    free(tmp1);

    free(line);

    return true;
}

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

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

        }
        free(cursor);
    }
    // TODO
    return true;
}

:) dictionary.c, dictionary.h, and Makefile exist

:) speller compiles

:) handles most basic words properly

:) handles min length (1-char) words

:) handles max length (45-char) words

:) handles words with apostrophes properly

:) spell-checking is case-insensitive

:) handles substrings properly

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

Valgrind Error

0
-1

Your code has two kinds of memory errors: 1. read uninitialized memory; 2. read from freed memory. The following are the error messages. Here is the link to reproduce and debug it. Just click "Run"

  Memory access warning: reading uninitialized memory.
  # Reading 1 bytes from 0x88bc430 will read undefined data.
  #
  # The memory-space-to-be-read (start:0x88bc430, size:52 bytes) is allocated at
  #    file:/dictionary.c::89, 20
  # It is not initialized.
  #
  #  0x88bc430               0x88bc463
  #  +------------------------------+
  #  | the memory-space-to-be-read  |
  #  +------------------------------+
  #  ^~~~~~~~~~
  #      the read starts at the begin of the memory-space.
  #
  # Stack trace (most recent call first) of the read.
  # [0]  file:/musl-1.1.10/src/string/strcasecmp.c::8, 2
  # [1]  file:/dictionary.c::36, 13
  # [2]  file:/speller.c::112, 32
  # [3]  [libc-start-main]
  # This detection can be configured with DTS_MEMORY_UNINIT_CHECK=<error|warning|disabled>.

  Memory access error: reading from a freed memory space; abort execution.
  # Reading 1 bytes from 0x88bd1f0 will read undefined values.
  #
  # The memory-space-to-be-read (start:0x88bd1f0, size:52 bytes) was allocated at
  #    file:/dictionary.c::89, 20
  # It was freed, and its allocation location might be distorted by subsequent reuses.
  #
  #
  # Stack trace (most recent call first) of the read.
  # [0]  file:/musl-1.1.10/src/string/strcasecmp.c::8, 2
  # [1]  file:/dictionary.c::36, 13
  # [2]  file:/speller.c::112, 32
  # [3]  [libc-start-main]

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .