Я работаю над программой проверки орфографии, где нам нужно загрузить словарь в таблицу ha sh, а затем сравнить любой текст со словами в этом словаре. Valgrind сообщает мне, что у меня происходит утечка памяти, но ошибок не обнаружено. Мой код ниже. Я действительно считаю, что проблема в функции загрузки, но я не могу ее понять. Вывод Valgrind также ниже.
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <ctype.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 = 500000;
// Hash table
node *table[N];
//Keep track of word count
int word_count = 0;
//Check if dic was loaded
bool dic_loaded = false;
// Returns true if word is in dictionary else false
bool check(const char *word)
//hash function is not case sensitive. Adding a loop to lowercase all letters before returning hash index source
//https://stackoverflow.com/questions/2661766/how-do-i-lowercase-a-string-in-c
{
char lower_case[strlen(word)]; // opens variable
strcpy(lower_case, word); // copies string to new variable
for(int i = 0; i < strlen(word); i++) // iterates variable
{
lower_case[i] = tolower(lower_case[i]); // converts each char.
}
//hash the word
unsigned int index = hash(lower_case);
//access index
node *cursor = NULL;
cursor = table[index];
// loop indexes and compare words
for (int i = 0; i < N; i++)
{
while (cursor != NULL)
{
if (strcasecmp (cursor -> word, lower_case) == 0)
{
return true;
}
else
{
cursor = cursor -> next;
}
}
}
return false;
}
// Hashes word to a number
// source: 04 - http://www.cse.yorku.ca/~oz/hash.html loselose - only one that didnt seg fault
unsigned int hash(const char *word)
{
unsigned int hash = 0;
int c;
while ((c = *word++))
{
hash += c;
}
return hash;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
char word[LENGTH + 1];
// open dictionary file and check if null
FILE *dictionary_file = fopen(dictionary, "r");
if (dictionary_file == NULL)
{
return false;
}
// create empty buckets
for (int i = 0; i < N; i++)
{
table[i] = NULL;
}
// create loop to scan through all the words from *dictionary_file
while (fscanf(dictionary_file, "%s", word) != EOF)
{
//count each word for size()
word_count++;
//Alocate memory for a node
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
//copy string from dictionary into a node
strcpy (n -> word, word);
n -> next = NULL;
//call hash function to return an index and store it into a temp node
int index = hash(word);
//create list head
if (table[index] == NULL)
{
table[index] = n;
n -> next = NULL;
}
else // keeps adding the next node
{
n->next = table[index];
table[index] = n;
}
}
dic_loaded = true;
fclose(dictionary_file);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
if (dic_loaded)
{
return word_count;
}
return 0;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
//iterate throught the linked list
for (int i = 0; i < N; i++)
{
// set cursor to table index
node *cursor = table[i];
while (cursor != NULL)
{
node *temp = cursor; // set temp to table index
cursor = cursor -> next; // move cursor
free(temp); // free temp
}
return true;
}
return false;
}
RDS MISSPELLED: 0
WORDS IN DICTIONARY: 143091
WORDS IN TEXT: 6
TIME IN load: 1.35
TIME IN check: 0.00
TIME IN size: 0.00
TIME IN unload: 0.00
TIME IN TOTAL: 1.36
==1285==
==1285== HEAP SUMMARY:
==1285== in use at exit: 8,013,096 bytes in 143,091 blocks
==1285== total heap usage: 143,096 allocs, 5 frees, 8,023,416 bytes allocated
==1285==
==1285== 8,013,096 bytes in 143,091 blocks are still reachable in loss record 1 of 1
==1285== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1285== by 0x4012DD: load (dictionary.c:125)
==1285== by 0x4009B4: main (speller.c:40)
==1285==
==1285== LEAK SUMMARY:
==1285== definitely lost: 0 bytes in 0 blocks
==1285== indirectly lost: 0 bytes in 0 blocks
==1285== possibly lost: 0 bytes in 0 blocks
==1285== still reachable: 8,013,096 bytes in 143,091 blocks
==1285== suppressed: 0 bytes in 0 blocks
==1285==
==1285== For counts of detected and suppressed errors, rerun with: -v
==1285== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)