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)