【问题标题】:pset 5 I can't find where I am leaking memorypset 5 我找不到内存泄漏的位置
【发布时间】:2020-06-19 10:16:50
【问题描述】:

任何人都可以帮助/指导我找到这段代码有内存泄漏的地方吗?

这是代码

// 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行。

【问题讨论】:

  • node *h = malloc(sizeof(node)); 看起来是个问题
  • 从不以任何方式使用h,除了检查分配是否成功。
  • 哦,是的,谢谢!我已经摆脱了它,但它仍然向我显示同样的错误

标签: c memory-leaks cs50


【解决方案1】:

问题似乎是您没有使用 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;
}

另外,如上述 cmets 所述,我看不出使用 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;
}

【讨论】:

  • 非常感谢...但它仍然向我显示相同的错误..
  • @alex0110 我在代码中添加了更多的 free() 调用,你能再检查一下吗?如果这不能解决,你能分享你的主要吗?
  • 我搞定了...非常感谢...我的主代码有问题...就像我的代码中有错误一样。一旦我修复了这个错误,内存泄漏就会自行解决
猜你喜欢
  • 2020-08-19
  • 2014-08-26
  • 1970-01-01
  • 2018-04-07
  • 2017-11-14
相关资源
最近更新 更多