Valgrind:仍可达到的内存泄漏(CS50 PSET5:Speller)

时间:2020-07-23 17:41:27

标签: c memory-leaks hashtable valgrind cs50

正在通过valgrind发现“仍然可以到达”的内存泄漏。我读过“仍然可以到达”的泄漏通常不是问题,但是我希望代码完美无缺,而且泄漏8,012,816字节似乎很多。代码和valgrind结果如下。

我尝试释放您可以想象的所有内容(fclose filefree mallocglobal variablesnodes),然后绕圈转。我假设问题出在加载或卸载函数,更可能是后者,因为我不确定是否要删除所有哈希表节点以及链接列表节点。也许我创建了太多的NULL节点,因为它们是NULL而没有被释放?当我将哈希表大小(N)更改为1时,没有泄漏,但是它是一个只有1个链表的无用哈希表!当前N是任意的26 x 26 x 26-不知道这应该是什么,或者是否有一种计算最优值的方法?感谢您的帮助!

// Implements a dictionary's functionality

#include <stdbool.h> // bools
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h> // string case compare
#include <string.h> // strings
#include <ctype.h> // upper/lowercase

#include "dictionary.h"

int word_count = 0; // Counts words as they are loaded into hashtable by the load function below.

// 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 = 17576;

// Hash table
node *table[N];

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    int key = hash(word);
    node* cursor = table[key];

    while(cursor != NULL)
    {
        if(strcasecmp(cursor -> word, word) == 0)
        {
        return true;
        }
        cursor = cursor -> next;
    }
return false;

}

// Hashes word to a number
unsigned int hash(const char *word)
{
    unsigned int hash = 0;
    for (int i = 0 ; word[i] != '\0' ; i++)
    {
        hash = 31*hash + tolower(word[i]);
    }
    return hash % N;
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    FILE* file = fopen(dictionary, "r");

    if(file == NULL)
    {
        fclose(file);
        return false;
    }

    // Initialise hashtable buckets
    for(int i = 0; i < N; i++)
    {
        table[i] = NULL;
    }

    // Read every word until end of file and makes copy to temp_node
    char temp_word[LENGTH +1];

    while(fscanf(file, "%s\n", temp_word) != EOF)
    {
        node* temp_node = malloc(sizeof(node));

        if(temp_node == NULL)
        {
            return false;
        }

        strcpy(temp_node -> word, temp_word);
        int k = hash(temp_word);

        if(table[k] == NULL)
        {
            temp_node -> next = NULL;
            table[k] = temp_node;
        }

        else
        {
            temp_node -> next = table[k];
            table[k] = temp_node;

        }
        word_count++;
    }
    fclose(file);
    return true;
}

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    return word_count;
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    node* cursor = NULL;
    
    for(int i = 0; i < N; i++)
    {
        cursor = table[i];

        while(cursor != NULL)
        {
            node* temp = cursor;
            cursor = cursor -> next;
            free(temp);
        }
    return true;    
    }
return false;
}

**

HEAP SUMMARY:

in use at exit: 8,012,816 bytes in 143,086 blocks
total heap usage: 143,096 allocs, 10 frees, 8,023,416 bytes allocated
8,012,816 bytes in 143,086 blocks are still reachable in loss record 1 of 1

at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

by 0x4011F3: load (dictionary.c:83)

by 0x400964: main (speller.c:40)

LEAK SUMMARY:

definitely lost: 0 bytes in 0 blocks

indirectly lost: 0 bytes in 0 blocks

possibly lost: 0 bytes in 0 blocks

still reachable: 8,012,816 bytes in 143,086 blocks

suppressed: 0 bytes in 0 blocks

For counts of detected and suppressed errors, rerun with: -v

ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)**

0 个答案:

没有答案