繁体   English   中英

CS50 拼写器在某处有 memory 泄漏......我找不到它

[英]CS50 Speller has a memory leak somewhere... and I can't find it

我目前正在学习 CS50x,并且正在学习 Pset5:Speller。 我的代码按预期工作,但是当我运行 check50 function 时,我的程序失败了 Valgrind。

这让我特别困惑,因为当我使用 help50 在我的程序上运行 Valgrind 时,它通过时没有 memory 泄漏。 在将默认字典更改为字典/小之后,我在我的程序上运行了 help50 Valgrind,它仍然通过了。

这是我的代码和我从 check50 获得的错误日志。 我相信 Valgrind 错误是因为没有在文件上使用 fclose(),但是如果我包含 fclose(),那么我的程序在使用“munmap_chunk():无效指针”运行时会失败。

如果有人可以帮助我或知道我应该在哪里看,我将不胜感激!

// Implements a dictionary's functionality

#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>

#include "dictionary.h"

// Represents a node in a hash table
typedef struct node
{
    char word[LENGTH + 1];
    struct node *next;
}
node;

// Number of bucket for Hash Table
const unsigned int N = 676;

// Hash table
node *table[N];

int word_counter = 0;

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    // TODO
    int index = hash(word);
    node *cursor = table[index];
    //printf("cursor: %s\n", cursor->word);

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

    }

    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO: Improve this hash function

    unsigned int index = 0;
    for (int i = 0; i < 26; i++)
    {
        if (word[0] == i + 'a' || word[0] == i + 'A')
        {
            index += i * 26;
        }

        if (word[1] == i + 'a' || word[1] == i + 'A')
        {
            index += i;
        }
    }

return index;
}

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

    table_clear();

    // Use fscanf() to look at each string in the dictionary and store to buffer
    char *buffer = malloc(sizeof(LENGTH + 1));
    if (buffer == NULL)
    {
        return false;
    }
    while (fscanf(dict_file, "%s", buffer) != EOF)
    {
        // Create a new memory space for each dictionary word, and store it here
        node *n = malloc(sizeof(node));
        if (n == NULL)
        {
            free(buffer);
            return false;
        }
        // Copy each word from buffer to the location (*dict_entry).word
        strcpy(n->word, buffer);
        n->next = NULL;

        // Use hash function to find the hash value of the dictionary word
        int index = hash(n->word);
        if (table[index] != NULL)
        {
            n->next = table[index];
        }
        table[index] = n;
        n = NULL;
        free(n);
        word_counter++;
    }
    //fclose(dict_file); <----- If activate, this line causes the munmap_chunk: invalid pointer error
    free(buffer);
    return true;
}

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

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

        free(cursor);
     }

    return true;
}

// Sets every value in table to NULL
void table_clear(void)
{
    for (int i = 0; i < N; i++)
    {
        table[i] = NULL;
    }
    return;
}

**Cause valgrind tests failed; see log for more information

LOG:
running valgrind --show-leak-kinds=all --xml=yes --xml-file=/tmp/tmpr2rknwok -- ./speller substring/dict substring/text...
checking for output "MISSPELLED WORDS\n\nca\ncats\ncaterpill\ncaterpillars\n\nWORDS MISSPELLED: 4\nWORDS IN DICTIONARY: 2\nWORDS IN TEXT: 6\n"...
checking that program exited with status 0...
checking for valgrind errors...
Invalid write of size 1: (file: dictionary.c, line: 88)
Invalid read of size 1: (file: dictionary.c, line: 99)
472 bytes in 1 blocks are still reachable in loss record 1 of 1: (file: dictionary.c, line: 74)

见上文解释

正如评论中指出的那样,该程序存在许多问题,但 valgrind 错误报告最有可能的罪魁祸首是这种动态分配:

char *buffer = malloc(sizeof(LENGTH + 1));

它分配sizeof表达式(LENGTH + 1)字节数,这很可能与执行sizeof(int)相同 - 通常为 4 - 而 4 个字节将无法存储超过 3 个char的单词秒。 我说最有可能是因为我不知道LENGTH的类型,但我假设它是一个int ,在这种情况下,您实际上可以执行char *buffer = malloc(sizeof(int)); .

它应该是:

char *buffer = malloc(LENGTH + 1);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM