CS50 / pset5 / speller内存泄漏

时间:2020-07-21 19:15:24

标签: memory-leaks valgrind cs50

有人可以帮我吗?我究竟做错了什么?我不完全知道需要修复哪一部分,我认为它在卸载功能中。

这是我的代码:

// Implements a dictionary's functionality
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "dictionary.h"

#define HASHTABLE_SIZE 10000

// Defines struct for a node
typedef struct node
{
    char word[LENGTH + 1];
    struct node *next;
}
node;

node *hashtable[HASHTABLE_SIZE];

// Hashes the word (hash function posted on reddit by delipity)
int hash_index(char *hash_this)
{
    unsigned int hash = 0;
    for (int i = 0, n = strlen(hash_this); i < n; i++)
    {
        hash = (hash << 2) ^ hash_this[i];
    }
    return hash % HASHTABLE_SIZE;
}

// Initializes counter for words in dictionary
int word_count = 0;

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
   // Opens dictionary
    FILE *file = fopen(dictionary, "r");
    if (file == NULL)
    {
        return false;
    }
    // Scans dictionary word by word
    char word[LENGTH + 1];
    while (fscanf(file, "%s", word) != EOF)
    {
        // Mallocs a node for each new word (i.e., creates node pointers)
        node *new_node = malloc(sizeof(node));
        node *cursor;
        node *tmp;

        // Checks if malloc succeeded, returns false if not
        if (new_node == NULL)
        {
            unload();
            return false;
        }
        // Copies word into node if malloc succeeds
        strcpy(new_node->word, word);

        // Initializes & calculates index of word for insertion into hashtable
        int h = hash_index(new_node->word);

        // Initializes head to point to hashtable index/bucket
        node *head = hashtable[h];

        // Inserts new nodes at beginning of lists
        if (head == NULL)
        {
            hashtable[h] = new_node;
            word_count++;
        }
        else
        {
            new_node->next = hashtable[h];
            hashtable[h] = new_node;
            word_count++;
        }
    }
    fclose(file);
    return true;
}

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    // Creates copy of word on which hash function can be performed
    int n = strlen(word);
    char word_copy[LENGTH + 1];
    for (int i = 0; i < n; i++)
    {
        word_copy[i] = tolower(word[i]);
    }
    // Adds null terminator to end string
    word_copy[n] = '\0';

    // Initializes index for hashed word
    int h = hash_index(word_copy);

    // Sets cursor to point to same address as hashtable index/bucket
    node *cursor = hashtable[h];

    // Sets cursor to point to same location as head
    while (cursor != NULL)
    {
        // If strcasecmp returns true, then word has been found
        if (strcasecmp(cursor->word, word_copy) == 0)
        {
            return true;
        }

        // Else word has not yet been found, advance cursor
        else
        {
            cursor = cursor->next;
        }
    }

        // Cursor has reached end of list, word not found in dictionary (misspelled)
            return false;
}

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

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    node *head = NULL;
    node *cursor = head;
    // freeing linked lists
    while (cursor != NULL)
    {
        node *temp = cursor;
        cursor = cursor->next;
        free(temp);
    }
    return true;
}

这些是来自check50的结果:

:) dictionary.c, dictionary.h, and Makefile exist
:) speller compiles
:) handles most basic words properly
:) 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
:( program is free of memory errors
valgrind tests failed; rerun with --log for more information.

这些是我运行valgrind时的结果:

==595== Memcheck, a memory error detector
==595== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==595== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==595== Command: ./speller texts/cat.txt
==595== 

MISSPELLED WORDS


WORDS MISSPELLED:     0
WORDS IN DICTIONARY:  143091
WORDS IN TEXT:        6
TIME IN load:         1.39
TIME IN check:        0.00
TIME IN size:         0.00
TIME IN unload:       0.00
TIME IN TOTAL:        1.40

==595== 
==595== HEAP SUMMARY:
==595==     in use at exit: 8,013,096 bytes in 143,091 blocks
==595==   total heap usage: 143,096 allocs, 5 frees, 8,023,416 bytes allocated
==595== 
==595== 8,013,096 bytes in 143,091 blocks are still reachable in loss record 1 of 1
==595==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==595==    by 0x401175: load (dictionary.c:52)
==595==    by 0x4009B4: main (speller.c:40)
==595== 
==595== LEAK SUMMARY:
==595==    definitely lost: 0 bytes in 0 blocks
==595==    indirectly lost: 0 bytes in 0 blocks
==595==      possibly lost: 0 bytes in 0 blocks
==595==    still reachable: 8,013,096 bytes in 143,091 blocks
==595==         suppressed: 0 bytes in 0 blocks
==595== 
==595== For counts of detected and suppressed errors, rerun with: -v
==595== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

我真的很坚持,非常感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

您是正确的,问题在于卸载。仔细看一下这个顺序:

    node *head = NULL;
    node *cursor = head;
    // freeing linked lists
    while (cursor != NULL)

cursor首次到达while时的值是什么?

hashtable是链接列表的标题。它需要在unload函数中提到。