1

I have completed pset5 and passed check50.

But when i run it with valgrind, it is showing the following errors:-

==12042== Memcheck, a memory error detector
==12042== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==12042== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==12042== Command: ./speller texts/austinpowers.txt
==12042== 
==12042== Conditional jump or move depends on uninitialised value(s)
==12042==    at 0x4011EA: load (dictionary.c:101)
==12042==    by 0x40087D: main (speller.c:40)
==12042==  Uninitialised value was created by a heap allocation
==12042==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12042==    by 0x400FE3: createnode (dictionary.c:21)
==12042==    by 0x4011F4: load (dictionary.c:103)
==12042==    by 0x40087D: main (speller.c:40)
==12042== 
==12042== Use of uninitialised value of size 8
==12042==    at 0x4011E1: load (dictionary.c:101)
==12042==    by 0x40087D: main (speller.c:40)
==12042==  Uninitialised value was created by a heap allocation
==12042==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12042==    by 0x400FE3: createnode (dictionary.c:21)
==12042==    by 0x4011F4: load (dictionary.c:103)
==12042==    by 0x40087D: main (speller.c:40)
==12042== 
==12042== Invalid read of size 8
==12042==    at 0x4011E1: load (dictionary.c:101)
==12042==    by 0x40087D: main (speller.c:40)
==12042==  Address 0xa1 is not stack'd, malloc'd or (recently) free'd
==12042== 
==12042== 
==12042== Process terminating with default action of signal 11 (SIGSEGV)
==12042==  Access not within mapped region at address 0xA1
==12042==    at 0x4011E1: load (dictionary.c:101)
==12042==    by 0x40087D: main (speller.c:40)
==12042==  If you believe this happened as a result of a stack
==12042==  overflow in your program's main thread (unlikely but
==12042==  possible), you can try to increase the size of the
==12042==  main thread stack using the --main-stacksize= flag.
==12042==  The main thread stack size used in this run was 8388608.
==12042== 
==12042== HEAP SUMMARY:
==12042==     in use at exit: 78,291,032 bytes in 349,512 blocks
==12042==   total heap usage: 349,512 allocs, 0 frees, 78,291,032 bytes allocated
==12042== 
==12042== LEAK SUMMARY:
==12042==    definitely lost: 0 bytes in 0 blocks
==12042==    indirectly lost: 0 bytes in 0 blocks
==12042==      possibly lost: 0 bytes in 0 blocks
==12042==    still reachable: 78,291,032 bytes in 349,512 blocks
==12042==         suppressed: 0 bytes in 0 blocks
==12042== Reachable blocks (those to which a pointer was found) are not shown.
==12042== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==12042== 
==12042== For counts of detected and suppressed errors, rerun with: -v
==12042== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
Segmentation fault

It seems to show that I am using uninitialized data although I am setting the values to NULL in createnode() function.

And there also seems to be some issue with unload() as it shows that I am not able to free any of the allocated memory.

Here's my code:

/**
 * Implements a dictionary's functionality.
 */

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

#include "dictionary.h"

// Root Node
node *root = NULL;

// Tracks No. of words in dictionary
int words = 0;

node *createnode(void)
{
    // allocate memory for new node
    node* new_node = (node*) malloc(sizeof(node));

    new_node->is_word = false;

    // set all pointers to NULL
    for (int i = 0; i < 27; i++)
        new_node->children[i] = NULL;

    return new_node;
}


/**
 * Returns true if word is in dictionary else false.
 */
bool check(const char *word)
{
    node *trav = root;
    int c;
    int i = 0;

    do
    {
        // Reads characters of words one by one
        c = word[i];

        // change to lowercase
        if(c <= 90 && c >= 65) 
        {
            c += 32;
        }

        // Only allows alphabets or apostrophe
        if((c >= 97 && c <= 122) || (c == '\''))
        {
            if(trav->children[c - 96] == NULL)
            {
                return false;
            }
            else
            {
                trav = trav->children[c - 96];
            }
        }

        i++;
    }while(c != '\0');

    return trav->is_word;
}


/**
 * Loads dictionary into memory. Returns true if successful else false.
 */
bool load(const char *dictionary)
{
    // open input file
    FILE *dict = fopen(dictionary, "r");

    if(dict == NULL)
    {
        printf("File doesn't exist.\n");
        return false;
    }

    char c;

    // memory aloocation to root node
    root = createnode();

    // Node trav to tranverse through the linked list
    node *trav = root;

    do
    {
        c = fgetc(dict);
        if(isalpha(c) || c == '\'')
        {
            // Checks if the node already exists or not
            if(trav->children[c-96] == NULL)
            {
                trav->children[c-96] = createnode();
            }
            trav = trav->children[c-96];
        }
        else if(c == '\n')
        {
            // Sets is_word to true when we reach end of the word
            trav->is_word = true;
            words++;
            trav = root;
        }


    }while(c != EOF);

    fclose(dict);
    return true;
}


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

bool delnode(node *trav)
{
    // calls function delnode on every node in node's children
    for(int i = 0; i < 27; i++)
    {
        if(trav->children[i] != NULL)
        {
            return delnode(trav->children[i]);    
        }

    }

    free(trav);
    return true;
}

/**
 * Unloads dictionary from memory. Returns true if successful else false.
 */
bool unload(void)
{

    // calls recursive function delnode 
    return delnode(root);

}

I have no idea where I am going wrong and so could really use some help.

1 Answer 1

1

Your problem arises when you read an apostrophe in load(). You have:

c = fgetc(dict);
if(isalpha(c) || c == '\'')
{
    // Checks if the node already exists or not
    if(trav->children[c-96] == NULL)
    {
        trav->children[c-96] = createnode();
    }
    trav = trav->children[c-96];
}

But if c is an apostrophe ('), c-96 is 39-96 == -57 since in the ASCII table the apostrophe is equal to 39 in decimal.

Then when you try to check if(trav->children[c-96] == NULL), trav->children[-57] is not initialized to NULL, and valgrind is complaining.

I think this should also give you a segmentation fault.

Modify your code accordingly.

You must log in to answer this question.

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