0

Baby programmer over here. Before moving on to the (check) function, I wanted to make sure the (load) function was correct.

After performing Valgrind, I received the following errors. Up to this point, Valgrind has been very helpful as it shows the stack trace and tells me where the errors are occurring. However, this time I am unable to make sense of the stack trace results provided by Valgrind.

From what I can see, my memory errors are of type "Invalid read/write" and somehow involve the fscanf function in my code. I know that invalid read/write errors have to do with writing/reading outside bounds allocated. However, I have not been able to find where those errors have been committed.

Attached is copy of dicionary.c (where all functions (including load) are declared and defined for use in speller) as well as the valgrind error received.

Any help would be appreciated! Thanks!

    // Implements a dictionary's functionality
    
    #include <stdbool.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.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 = 35000;
    
    // Hash table
    node *table[N];
    
    //Global variables
    int word_count_inserted = 0;
    
    // Returns true if word is in dictionary else false
    bool check(const char *word)
    {
        // TODO
        return false;
    }
    
    // Hashes word to a number. Hash function found on https://cs50.stackexchange.com/questions/37209/pset5-speller-hash-function
    unsigned int hash(const char *word)
    
        {
            unsigned int hash_value = 0;
            for (int i = 0, n = strlen(word); i < n; i++)
            {
                 hash_value = (hash_value << 2) ^ word[i];
            }
            return hash_value % N; //N is size of hashtable
        }
    
    // Loads dictionary into memory, returning true if successful else false
    bool load(const char *dictionary)
    {
    
    //setting all node pointers in hash table to NULL
    for (int i = 0; i < N;i++)
    {
        table[i] = NULL;
    }
       //open dictionary file
    
       FILE * dictfile=fopen(dictionary,"r");
        //Ensure successful opening of file
         if (dictfile == NULL)
            {
                printf("Dictionary file cannot be opened for reading \n");
                return 1;
            }
               
               //dynamic array where each word will be stored
    
      char* word= malloc(sizeof(char)*(LENGTH+1));
      if (word == NULL)
        {
            return 1;
        }
    
       //Read strings from file word by word 
       
      while(fscanf(dictfile, "%s", word) != EOF)
    {
    
      //creates new node for each word
       node*n= malloc(sizeof(node));
       if (n == NULL)
       {
           return 1;
       }
    
       strcpy(n->word, word);
       n-> next = NULL;
    
    //Call to hash function
    
     int hashed_value = hash(word);
    
    // Insert node into Hash Table
    
    n->next=table[hashed_value];
    table[hashed_value]=n;
    word_count_inserted = word_count_inserted + 1;
    
    
       //free mem before next word ?
       free(word);
       free(n);
    
    }
    
    return 0;
    
    }

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
   return word_count_inserted;
   printf ("%d\n",word_count_inserted);


   if (word_count_inserted == 0)
    {
     return 0;
    }
}

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

Valgrind output

        ~/pset5/speller/ $ valgrind ./speller texts/cat.txt
        ==5952== Memcheck, a memory error detector
        ==5952== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
        ==5952== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
        ==5952== Command: ./speller texts/cat.txt
==5952== 
==5952== Invalid write of size 1
==5952==    at 0x524704D: _IO_vfscanf (vfscanf.c:1103)
==5952==    by 0x5256355: __isoc99_fscanf (isoc99_fscanf.c:34)
==5952==    by 0x40114C: load (dictionary.c:76)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Address 0x55cb2b0 is 0 bytes inside a block of size 46 free'd
==5952==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x4011DE: load (dictionary.c:102)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Block was alloc'd at
==5952==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x401116: load (dictionary.c:69)
==5952==    by 0x400914: main (speller.c:40)
==5952== 
==5952== Invalid write of size 1
==5952==    at 0x52489B2: _IO_vfscanf (vfscanf.c:1188)
==5952==    by 0x5256355: __isoc99_fscanf (isoc99_fscanf.c:34)
==5952==    by 0x40114C: load (dictionary.c:76)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Address 0x55cb2b3 is 3 bytes inside a block of size 46 free'd
==5952==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x4011DE: load (dictionary.c:102)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Block was alloc'd at
==5952==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x401116: load (dictionary.c:69)
==5952==    by 0x400914: main (speller.c:40)
==5952== 
==5952== Invalid read of size 1
==5952==    at 0x5355BC0: __strcpy_ssse3 (strcpy-ssse3.S:32)
==5952==    by 0x401184: load (dictionary.c:86)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Address 0x55cb2b0 is 0 bytes inside a block of size 46 free'd
==5952==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x4011DE: load (dictionary.c:102)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Block was alloc'd at
==5952==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x401116: load (dictionary.c:69)
==5952==    by 0x400914: main (speller.c:40)
==5952== 
==5952== Invalid read of size 1
==5952==    at 0x4C32E03: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x401184: load (dictionary.c:86)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Address 0x55cb2b1 is 1 bytes inside a block of size 46 free'd
==5952==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x4011DE: load (dictionary.c:102)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Block was alloc'd at
==5952==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x401116: load (dictionary.c:69)
==5952==    by 0x400914: main (speller.c:40)
==5952== 
==5952== Invalid read of size 1
==5952==    at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x401042: hash (dictionary.c:40)
==5952==    by 0x40119D: load (dictionary.c:91)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Address 0x55cb2b0 is 0 bytes inside a block of size 46 free'd
==5952==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x4011DE: load (dictionary.c:102)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Block was alloc'd at
==5952==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x401116: load (dictionary.c:69)
==5952==    by 0x400914: main (speller.c:40)
==5952== 
==5952== Invalid read of size 1
==5952==    at 0x4C32D04: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x401042: hash (dictionary.c:40)
==5952==    by 0x40119D: load (dictionary.c:91)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Address 0x55cb2b1 is 1 bytes inside a block of size 46 free'd
==5952==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x4011DE: load (dictionary.c:102)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Block was alloc'd at
==5952==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x401116: load (dictionary.c:69)
==5952==    by 0x400914: main (speller.c:40)
==5952== 
==5952== Invalid read of size 1
==5952==    at 0x401062: hash (dictionary.c:42)
==5952==    by 0x40119D: load (dictionary.c:91)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Address 0x55cb2b0 is 0 bytes inside a block of size 46 free'd
==5952==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x4011DE: load (dictionary.c:102)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Block was alloc'd at
==5952==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x401116: load (dictionary.c:69)
==5952==    by 0x400914: main (speller.c:40)
==5952== 
==5952== Invalid free() / delete / delete[] / realloc()
==5952==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x4011DE: load (dictionary.c:102)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Address 0x55cb2b0 is 0 bytes inside a block of size 46 free'd
==5952==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x4011DE: load (dictionary.c:102)
==5952==    by 0x400914: main (speller.c:40)
==5952==  Block was alloc'd at
==5952==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x401116: load (dictionary.c:69)
==5952==    by 0x400914: main (speller.c:40)
==5952== 
Could not load dictionaries/large.
==5952== 
==5952== HEAP SUMMARY:
==5952==     in use at exit: 552 bytes in 1 blocks
==5952==   total heap usage: 143,095 allocs, 286,184 frees, 8,018,814 bytes allocated
==5952== 
==5952== 552 bytes in 1 blocks are still reachable in loss record 1 of 1
==5952==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5952==    by 0x5258EB9: __fopen_internal (iofopen.c:65)
==5952==    by 0x5258EB9: fopen@@GLIBC_2.2.5 (iofopen.c:89)
==5952==    by 0x4010E0: load (dictionary.c:60)
==5952==    by 0x400914: main (speller.c:40)
==5952== 
==5952== LEAK SUMMARY:
==5952==    definitely lost: 0 bytes in 0 blocks
==5952==    indirectly lost: 0 bytes in 0 blocks
==5952==      possibly lost: 0 bytes in 0 blocks
==5952==    still reachable: 552 bytes in 1 blocks
==5952==         suppressed: 0 bytes in 0 blocks
==5952== 
==5952== For counts of detected and suppressed errors, rerun with: -v
==5952== ERROR SUMMARY: 5756904 errors from 8 contexts (suppressed: 0 from 0)
    
-1

In the load() function, when you're opening the file, I don't think it's valid syntax to write FILE * dictfile = open... You should write either FILE* dictfile or FILE *dictfile.

Also in the load() function, when you're creating a node, you've written node*n= ... which should be invalid syntax. Write either node* n or node *n.

I think you could have found syntax errors just by compiling the code as well.

1
  • Hey there Ruby! The code compiles fine without any prolems.The code just will not run without aborting.I went ahead a made the changes to follow your suggestions and still no success. I think there are some memory issues which is why I am focusing on the valgrind results. – Valerie Bryant Nov 23 '20 at 19:00

You must log in to answer this question.

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