【问题标题】:CS50 Speller Valgrind and misspelled wordsCS50 Speller Valgrind 和拼写错误的单词
【发布时间】:2020-09-22 20:25:47
【问题描述】:

大家好,我正在做哈佛的 CS50,我偶然发现了一个非常有趣的问题,但我无法解决。该程序的想法是从大量单词列表中检查哪些单词拼写错误,并在最后释放内存。
这些是我无法纠正的错误。

:) dictionary.c, dictionary.h, and Makefile exist
:) speller compiles
:( handles most basic words properly
    expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:) handles min length (1-char) words
:) handles max length (45-char) words
:) handles words with apostrophes properly
:) spell-checking is case-insensitive
:) handles substrings properly

这些是具体的错误,

running ./speller basic/dict basic/text...
checking for output "MISSPELLED WORDS\n\n\nWORDS MISSPELLED: 0\nWORDS IN DICTIONARY: 8\nWORDS IN TEXT: 9\n"...

Expected Output:
MISSPELLED WORDS


WORDS MISSPELLED:     0
WORDS IN DICTIONARY:  8
WORDS IN TEXT:        9
Actual Output:
MISSPELLED WORDS

over

WORDS MISSPELLED:     1
WORDS IN DICTIONARY:  8
WORDS IN TEXT:        9

由于某些奇怪的原因,看起来拼写错误的单词实际上拼写正确。 另一个错误如下:

valgrind tests failed; rerun with --log for more information.
Log
running valgrind --show-leak-kinds=all --xml=yes --xml-file=/tmp/tmpicmfiai5 -- ./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...
112 bytes in 2 blocks are still reachable in defeat record 1 of 2: (file: dictionary.c, line: 76)
336 bytes in 6 blocks are definitely lost in defeat record 2 of 2: (file: dictionary.c, line: 31)

现在我将添加我的整个代码:

// Implements a dictionary's functionality
#include <strings.h>
#include <stdbool.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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 = 27;
int word_count;
char dictionary_word[LENGTH + 1];
// Hash table
node *table[N];

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

    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)
{
    int index = 0 ;
    for(int i = 0 ; word[i] != '\0' ; i++)
    {
        index += tolower(word[i]) ;
    }
    return index % N ;
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    // open the file
    FILE *file = fopen(dictionary, "r");
    // check if file is null
    if (!file)
    {
        fprintf(stderr, "File does not exist.\n");
        return false;
    }

    char word[LENGTH + 1];

    word_count = 0;

    while(fscanf(file, "%s", dictionary_word) != EOF)
    {
        // allocate memory for the new node
        node *new_node = malloc(sizeof(node));
        if (new_node == NULL)
        {
            return false;
        }

        strcpy(new_node->word, dictionary_word);
        int hashed = hash(dictionary_word);

        if(table[hashed] == NULL)
        {
            table[hashed] = new_node;
            new_node->next = NULL;
        }
        else
        {
            new_node->next = table[hashed];
            table[hashed] = new_node->next;
        }
        word_count++;
    }

    fclose(file);
    return true;
}


// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    //just return the word count, easy piesey.
    return word_count;
}


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

非常感谢,如果需要更多信息,我会在看到消息后立即提供。谢谢。

【问题讨论】:

  • dictionary.h 也不错。
  • 你在检查 malloc,但不要将它添加到任何列表中 - 哎呀你把它扔掉,只是在它上面分配表。这是不对的。
  • @MichaelDorgan 感谢您的评论,我将如何解决?抱歉
  • "现在我将添加我的整个代码:" --> 发布LENGTH 定义。更好的是minimal reproducible example
  • const unsigned int N = 27; ... node *table[N]; 不是有效的 C.

标签: c memory valgrind cs50


【解决方案1】:

我用small lalaland.txt 运行了你的代码,在dictionary.c::76 分配了两个内存块,在退出之前没有释放。以下是错误信息。你可以使用这个link 来重现它。对于malloc返回的所有内存块,需要调用free一次。您可以使用printf 找出哪些内存块没有被释放。最好使用小字典和小文本输入来进行此调试。

 Memory access warning: memory spaces are not freed; continue execution.
 # 2 memory spaces are allocated at
 #    file:/dictionary.c::76, 26
 # total 104 bytes
 #

【讨论】:

  • 所以我必须在卸载功能之前释放那些 malloc?
  • 你需要在unload函数中释放它们。
  • 首先,感谢您的链接。我添加了 free(cursor) 和 free(new_node) 并且弹出了相同的错误。事实上,当我尝试在卸载函数中添加 free(new_node) 时,我遇到了一个未声明的标识符错误。由我从字面上添加了这样的行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-20
  • 1970-01-01
  • 2020-06-06
  • 1970-01-01
  • 2020-08-25
  • 2020-10-18
  • 1970-01-01
相关资源
最近更新 更多