pset 5 Я не могу найти место утечки памяти - PullRequest
0 голосов
/ 19 июня 2020

Может ли кто-нибудь помочь / направить меня, чтобы найти, где этот код имеет утечку памяти?

Это код

// 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 байт памяти. Вы забыли освободить память, выделенную через mallo c? Присмотритесь к строке 109 словаря. c.

1 Ответ

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

Проблема, похоже, в том, что вы не используете free () для освобождения структур node* n и node* 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...