cs50拼写器一直提示free(): double free detected in tcache 2

cs50 speller keeps prompting free(): double free detected in tcache 2

我已经研究了这个问题集很长时间了,代码似乎是错误的,但我找不到解决方案。我一直在比较我的代码和其他人的代码,但我仍然不知道我哪里错了。如果您能为我提供一些解决此问题的方法,非常感谢您的帮助。它一直提示我 free(): double free detected in tcache 2 但我似乎找不到我的错误。

// Implements a dictionary's functionality

#include <stdbool.h>
#include <ctype.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 buckets in hash table
const unsigned int N = 50;

// Hash table
node *table[N];

//word count
int count = 0;

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    // TODO
    bool found = false;
    node *current = table[hash(word)];
    while (current != NULL)
    {
        if (strcasecmp(current -> word, word) == 0)
        {
            found = true;
        }
        else if(current -> next != NULL)
        {
            current = current -> next;
        }
        else
        {
            return false;
        }
    }
    return found;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO
    unsigned long hash = 5381;
    int c;
    while ((c = toupper(*word++)))
    {
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    }
    return hash % N;
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    // TODO
    FILE *infile = fopen(dictionary, "r");
    if (infile == NULL)
    {
        return false;
    }
    char buffer[LENGTH+1];
    while (fscanf(infile, "%s", buffer) != EOF)
    {   
        node *n = malloc(sizeof(node));
        strcpy(n -> word, buffer);
        n -> next = table[hash(buffer)];
        table[hash(buffer)] = n;
        count++;
        free(n);
    }
    fclose(infile);
    return true;
}

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

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

这个while循环中free的调用次数

while (fscanf(infile, "%s", buffer) != EOF)
{   
    node *n = malloc(sizeof(node));
    strcpy(n -> word, buffer);
    n -> next = table[hash(buffer)];
    table[hash(buffer)] = n;
    count++;
    free(n);
}

没有意义。您立即删除了(使用指针 nnode 类型的对象)您试图添加到 table 的内容(分配给类型 [= 的对象的有效地址) 14=]).结果 table 位置 hash(buffer) 的元素设置为

    table[hash(buffer)] = n;

有一个无效值,因为它是该语句中已删除节点的地址

    free(n);

因此在函数 unload 中,这个无效地址将再次用于释放函数 load 中已经释放的内存。

注意你没有像你在评论“for node n”中写的那样分配内存。 n 只是指向类型节点的已分配未命名对象的指针。所以你没有在这条语句

中释放指针n本身
    free(n);

您正在使用指针 n 释放类型节点的分配对象。因此,所有指向类型 node 的已分配对象的指针都变得无效。