Reputation: 515
I'm trying to run check50, but it says I have a memory leak issue. I ran help50 valgrind ./speller texts/cat.txt
, and it says:
==1430== Conditional jump or move depends on uninitialised value(s)
Looks like you're trying to use a variable that might not have a value? Take a closer look at line 36 of dictionary.c.
And also (the more complete message):
==1430==
==1430== HEAP SUMMARY:
==1430== in use at exit: 0 bytes in 0 blocks
==1430== total heap usage: 143,097 allocs, 143,097 frees, 8,023,462 bytes allocated
==1430==
==1430== All heap blocks were freed -- no leaks are possible
==1430==
==1430== For counts of detected and suppressed errors, rerun with: -v
==1430== ERROR SUMMARY: 492 errors from 2 contexts (suppressed: 0 from 0)
So I guess I have to edit my check function, but I don't know what else to do. Here is my program (I would really appreciate if you could help ;)):
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include "dictionary.h"
#define HASHTABLE_SIZE 65536
// 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 = HASHTABLE_SIZE;
// Hash table
node *table[N];
unsigned int totalWords = 0;
// Returns true if word is in dictionary else false
bool check(const char *word)
{
//Initialize lower case word
char lcword[LENGTH + 1];
for (int i = 0; i < LENGTH + 1; i++)
lcword[i] = tolower(word[i]);
node *cursor = table[hash(lcword)];
while (cursor != NULL)
{
if (strcasecmp(word, cursor->word) == 0)
{
return true;
}
cursor = cursor->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
//https://www.reddit.com/r/cs50/comments/1x6vc8/pset6_trie_vs_hashtable/cf9nlkn/
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 % HASHTABLE_SIZE;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
FILE *dicfile = fopen(dictionary, "r");
char *word = malloc(LENGTH + 1);
//Check if word is null
if (word == NULL)
return false;
//Check if the fopen function opened a not NULL file
if (dicfile == NULL)
return false;
//Iterate over dictionary until fscanf return EOF (meaning it's the end of the file)
while (fscanf(dicfile, "%s", word) != EOF)
{
//Create a node to store the current word
node *new_node = malloc(sizeof(node));
if (new_node == NULL)
return false;
//Copy the new_node's word into the current word
strcpy(new_node->word, word);
//Get the index (hash the current word and store it in n)
int n = hash(new_node->word);
//Insert the new_node into the linked list
new_node->next = table[n];
table[n] = new_node;
//Add to the total number of words in the text file
totalWords++;
}
fclose(dicfile);
free(word);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
return totalWords;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
for (int i = 0; i < HASHTABLE_SIZE; i++)
{
node* cursor = table[i];
node* tmp;
while (cursor != NULL)
{
tmp = cursor;
cursor = cursor->next;
free(tmp);
}
free(cursor);
}
return true;
}
And line 36 is this one:
lcword[i] = tolower(word[i]);
Thank you! Would love if you could solve this issue!
Upvotes: 0
Views: 300
Reputation: 515
The solution to this problem is in the type of the loop of the code. Instead of doing the for loop LENGTH
times, you just have to do it the same number of times as the size of word
. This is how it should look like:
//Initialize lower case word
char lcword[strlen(word) + 1];
for (int i = 0; i < strlen(word) + 1; i++)
lcword[i] = tolower(word[i]);
Upvotes: 1