pset 5我找不到内存泄漏的地方

时间:2020-06-19 10:16:50

标签: c memory-leaks cs50

有人可以帮助/指导我找到该代码在哪里泄漏内存吗?

这是代码

// Implements a dictionary's functionality

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.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 = 100;

// Hash table
node *table[N];

// Counter for size
int counter;

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    FILE *file = fopen(dictionary, "r");
    char w[LENGTH + 1];
    // Check if memory is available
    if (file == NULL)
        return false;

    while(fscanf(file, "%s", w) != EOF)
    {
        node *n = malloc(sizeof(node));
        // Check if memory is available
        if (n == NULL)
            return false;

        n->next = NULL;
        strcpy(n->word, w);
        int pos = hash(n->word);
        node *h = malloc(sizeof(node));
        if (h == NULL)
            table[pos] = n;
        else
        {
            n->next = table[pos];
            table[pos] = n;
        }
        counter++;
    }
    size();
    fclose(file);
    return true;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    int prod = 1;
    int len = strlen(word);
    for (int i = 0; i < len; i++)
    {
        prod *=  (int) word[i];
    }
    return prod % N;
}

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

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    int h = hash(word);
    node *ptr = malloc(sizeof(node));
    if (ptr == NULL)
        return false;
    ptr = table[h];
    while (true)
    {
        if (ptr == NULL)
            break;
        bool b = (strcasecmp(ptr->word, word)) == 0;
        if (b == true)
        {
            free(ptr);
            return b;
        }
        ptr = ptr->next;
    }
    free(ptr);
    return false;
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    for (int i = 0; i < N; i++)
    {
        node *ptr = malloc(sizeof(node));
        node *tmp = malloc(sizeof(node));
        if (ptr || tmp == NULL)
            return 1;
        ptr = table[i];
        // Free each linked list
        while (tmp != NULL)
        {
            tmp = ptr;
            ptr = ptr->next;
            free(tmp);
        }
        free(ptr);
    }

    return false;
}

这是help50 valgrind消息

寻求帮助...

==16020== 56 bytes in 1 blocks are definitely lost in loss record 1 of 7
==16020==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16020==    by 0x401302: unload (dictionary.c:109)
==16020==    by 0x400E09: main (speller.c:152)

看起来您的程序泄漏了56个字节的内存。您是否忘记释放通过malloc分配的内存?仔细查看Dictionary.c的第109行。

1 个答案:

答案 0 :(得分:0)

问题似乎是您没有使用free()来取消分配node* nnode* h结构。您必须按如下所示更改load()函数:

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    FILE *file = fopen(dictionary, "r");
    char w[LENGTH + 1];
    // Check if memory is available
    if (file == NULL)
        return false;

    while(fscanf(file, "%s", w) != EOF)
    {
        node *n = malloc(sizeof(node));
        // Check if memory is available
        if (n == NULL)
            return false;

        n->next = NULL;
        strcpy(n->word, w);
        int pos = hash(n->word);
        node *h = malloc(sizeof(node));
        if (h == NULL)
            table[pos] = n;
        else
        {
            n->next = table[pos];
            table[pos] = n;
        }
        counter++;
        free(n);
        free(h);
    }
    size();
    fclose(file);
    return true;
}

此外,如以上注释中所述,我看不到使用node * h的任何原因。您可以省略此部分:

if (h == NULL)
            table[pos] = n;
else
        {
            n->next = table[pos];
            table[pos] = n;
        }

对此:

n->next = table[pos];
table[pos] = n;

此外,unload()函数应如下更改:

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    for (int i = 0; i < N; i++)
    {
        node *ptr = malloc(sizeof(node));
        if (ptr == NULL) {
           return 1;
        }
        node *tmp = NULL;
        ptr = table[i];
        // Free each linked list
        while (ptr != NULL)
        {
            tmp = ptr;
            ptr = ptr->next;
            free(tmp);
        }
    }

    return false;
}