首页 > 解决方案 > 由于某种原因以及其他问题,代码似乎没有被释放

问题描述

所以不起作用的是我从 cs50 课程 check50 收到一条错误消息,它基本上告诉我它没有释放我的 malloc。确切的消息如下:

程序没有内存错误无法检查,直到皱眉倒转

现在我真的试图找出问题所在,但它一直困扰着我一段时间,我不明白。现在获取代码:https ://hastebin.com/liluyaqubo.cpp这有它。查看最后//一部分(卸载字典)。我试图让 valgrind 工作,但它没有,我可能没有它。对于那些对我正在做的事情感兴趣的人,这是:https ://cs50.harvard.edu/x/2020/psets/5/speller/ 这让我发疯了!

编辑:这是我写的 100 多行代码:关于这个问题,似乎是关于内存没有被正确释放的问题。它似乎超时了,因为 cs50 附带的调试器说它无法检查,直到皱眉倒转(AKA 它可以工作并且很好)。

// Implements a dictionary's functionality
#include <stdbool.h>
#include <strings.h>
#include "dictionary.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.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;

// Hash table
node *table[N];

int wordcount = 0;

// Returns true if word is in dictionary else false
bool check(const char *word) {
    char lowercase[LENGTH + 1];
    for (int i = 0; i < LENGTH + 1; i++) {
        lowercase[i] = tolower(word[i]);
    }
    node *cursor = table[hash(lowercase)];
    while (cursor != NULL) {
        if (strcmp(lowercase, cursor->word) == 0) {
            return true;
        }
        cursor = cursor->next;
    }
    return false;
}

unsigned int hash(const char *word) {
    unsigned int h = 0;
    for (int i = 0, n = strlen(word + 1); i < n; i++)
        h = (h << 2) ^ word[i];
    return h % N;
}

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

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

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

标签: cmallocfreecs50

解决方案


您的函数没有任何问题unload(),它正确释放了字典中的所有节点并将哈希表重置为所有空指针。

相反,您的代码中还有一些其他问题:

  • 将单词转换为小写的循环遍历整个数组,而它应该在空终止符处停止。
  • 应该将参数转换为避免char在签名的平台上对负值进行未定义的行为。tolower()(unsigned char)char
  • hash应该计算nn = strlen(word),而不是n = strlen(word + 1)。更好的是:您应该将循环更改为:for (int i = 0; word[i] != '\0'; i++)
  • false您应该在内存分配失败后返回之前关闭文件。
  • fscanf格式"%s\n"存在缺陷,因为一个比LENGTH字典中的字节长的单词会通过溢出目标数组而导致未定义的行为。您可以使用长度修饰符解决此问题:"%15s"ifLENGTH定义为16.
  • fscanf()停止返回时,循环应该停止1。碰巧这种特定的转换格式只能返回1or EOF,但如果输入流中的下一个字符不能以数字开头,"%d"则会返回。0
  • load()hash()为同一个词调用4 次。您应该计算一次哈希码并将其存储在局部变量中。
  • 尚不清楚为什么函数会size()增加全局变量wordcount

推荐阅读