I'm having a problem with memory leak, when I use Valgrind it tells me that I have 512bytes of memory leaked, I know the problem is with load because of Valgrind and because my load functions is returning false every time (in debug I can't step into the for loop, so the function step over to return false). Can someone help me with this ? How should I debug it ?
EDIT -> this is the loop inside the load function that both program and debugger are skipping (and the function only returns true inside the loop) :
for (int i = fgetc(dict); i == EOF; i = fgetc(dict)){
if (i == EOF){
fclose(dict);
return true;
}
nword[j] = i;
// when a "\" appears (only appears when fallowed by a "n") terminate the word.
if (nword[j] == '\\'){
nword[j] = '\0';
hash(nword);
// counts number of words
new_word++;
// so then the "n" is used before initiating a new word.
fgetc(dict);
// starts a new word.
j = 0;
}
j++;
}
This is the Valgrind log :
==3958== Memcheck, a memory error detector
==3958== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3958== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==3958== Command: ./speller texts/cat.txt
==3958==
Could not load dictionaries/large.
==3958==
==3958== HEAP SUMMARY:
==3958== in use at exit: 552 bytes in 1 blocks
==3958== total heap usage: 3 allocs, 2 frees, 5,672 bytes allocated
==3958==
==3958== 552 bytes in 1 blocks are still reachable in loss record 1 of 1
==3958== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3958== by 0x5258EB9: __fopen_internal (iofopen.c:65)
==3958== by 0x5258EB9: fopen@@GLIBC_2.2.5 (iofopen.c:89)
==3958== by 0x40135E: load (dictionary.c:120)
==3958== by 0x4008B4: main (speller.c:40)
==3958==
==3958== LEAK SUMMARY:
==3958== definitely lost: 0 bytes in 0 blocks
==3958== indirectly lost: 0 bytes in 0 blocks
==3958== possibly lost: 0 bytes in 0 blocks
==3958== still reachable: 552 bytes in 1 blocks
==3958== suppressed: 0 bytes in 0 blocks
==3958==
==3958== For counts of detected and suppressed errors, rerun with: -v
==3958== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0
And this is some of the code :
node *root = NULL;
int new_word = 0;
node *create_root(node *y)
{
y = malloc(sizeof(node));
if (root != NULL)
{
y->endOfWord = false;
for (int i = 0; i < 27; i++)
{
y->path[i] = NULL;
}
}
return y;
}
// Hashes word to a number
unsigned int hash(const char *word){
root = create_root(root);
node *tmp = root;
int index;
for (int j = 0; j < strlen(word); j++){
if (check_char(&word[j])){
index = CHAR_TO_INDEX(&word[j]);
if (word[j] == '\''){
index = 26;
}
if (!tmp->path[index]){
tmp->path[index] = create_root(tmp);
}
tmp = tmp->path[index];
}
else
return 1;
}
tmp->endOfWord = true;
return 0;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
FILE *dict = fopen(dictionary, "r");
if (dict == NULL){
return false;
}
int j = 0;
char nword[LENGTH];
for (int i = fgetc(dict); i == EOF; i = fgetc(dict)){
if (i == EOF){
fclose(dict);
return true;
}
nword[j] = i;
// when a "\" appears (only appears when fallowed by a "n") terminate the word.
if (nword[j] == '\\'){
nword[j] = '\0';
hash(nword);
// counts number of words
new_word++;
// so then the "n" is used before initiating a new word.
fgetc(dict);
// starts a new word.
j = 0;
}
j++;
}
return false;
}
void free_nodes(node *x){
if (!x){
return;
}
for (int i = 0; i < 26; i++){
if (x->path[i] != NULL){
free_nodes(x->path[i]);
}
else
continue;
}
free(x);
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
// TODO
free_nodes(root);
if(!root){
return true;
}
return false;
}