【问题标题】:CS50/pset5/speller memory leakCS50/pset5/speller 内存泄漏
【发布时间】:2020-07-21 19:15:24
【问题描述】:

有人可以帮我解决这个问题吗?我究竟做错了什么?我不完全知道我需要修复哪个部分,我认为它在卸载功能的某个地方。

这是我的代码:

// 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)

我真的坚持这一点,我将非常感谢一些帮助!

【问题讨论】:

    标签: memory-leaks valgrind cs50


    【解决方案1】:

    你是对的,问题是卸载。仔细看这个序列:

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

    cursor第一次到达while时的值是多少?

    hashtable 是链表的头部。它需要在unload 函数中的某处提及。

    【讨论】:

    • 我要写什么? node *cursor = hashtable[h]; ?对不起,我的大脑因思考解决方案而被炸毁,我知道我想多了。不想作弊什么的。谢谢!
    猜你喜欢
    • 2022-06-16
    • 2020-10-18
    • 2020-09-28
    • 2021-07-31
    • 1970-01-01
    • 2020-08-18
    • 2020-10-04
    • 1970-01-01
    • 2020-10-19
    相关资源
    最近更新 更多