CS50 Speller Valgrind和拼写错误的单词

时间:2020-06-04 00:00:38

标签: c memory valgrind cs50

大家好,所以我在做哈佛大学的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;
}

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

1 个答案:

答案 0 :(得分:0)

我使用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
 #