C утечка памяти при загрузке в таблицу ha sh - PullRequest
0 голосов
/ 19 июня 2020

Я работаю над программой проверки орфографии, где нам нужно загрузить словарь в таблицу 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)

1 Ответ

0 голосов
/ 19 июня 2020

OP утверждает, что во время компиляции / компоновки проблем не было:

Примечание: функция: strlen() возвращает size_t, а не int

gcc -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled2.c" -o "untitled2.o" 

untitled2.c:24:7: error: variably modified ‘table’ at file scope
 node *table[N];
       ^~~~~

untitled2.c: In function ‘check’:

untitled2.c:42:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i = 0; i < strlen(word); i++)  // iterates variable
                      ^

untitled2.c:44:25: warning: conversion to ‘char’ from ‘int’ may alter its value [-Wconversion]
         lower_case[i] = tolower(lower_case[i]); // converts each char.
                         ^~~~~~~

untitled2.c:49:26: warning: implicit declaration of function ‘hash’ [-Wimplicit-function-declaration]
     unsigned int index = hash(lower_case);
                          ^~~~

untitled2.c:49:26: warning: conversion to ‘unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]

untitled2.c:56:23: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for (int i = 0; i < N; i++)
                       ^

untitled2.c: At top level:
untitled2.c:82:14: error: conflicting types for ‘hash’
 unsigned int hash(const char *word)
              ^~~~

untitled2.c:49:26: note: previous implicit declaration of ‘hash’ was here
     unsigned int index = hash(lower_case);
                          ^~~~

untitled2.c: In function ‘hash’:

untitled2.c:89:14: warning: conversion to ‘unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
         hash += c;
              ^~

untitled2.c: In function ‘load’:

untitled2.c:110:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
    for (int i = 0; i < N; i++)
                      ^

untitled2.c:137:21: warning: conversion to ‘int’ from ‘unsigned int’ may change the sign of the result [-Wsign-conversion]
         int index = hash(word);
                     ^~~~

untitled2.c: In function ‘size’:

untitled2.c:168:16: warning: conversion to ‘unsigned int’ from ‘int’ may change the sign of the result [-Wsign-conversion]
         return word_count;
                ^~~~~~~~~~

untitled2.c: In function ‘unload’:
untitled2.c:178:23: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for (int i = 0; i < N; i++)
                       ^

Compilation failed.
...