问题描述
所以不起作用的是,我从cs50课程check50收到了一条错误消息,它基本上告诉我它没有释放我的malloc。确切的消息如下:
程序没有内存错误 直到皱着眉头,才能检查
现在,我真的试图找出出什么问题了,但是它一直困扰着我一段时间,我不明白。现在输入代码:https://hastebin.com/liluyaqubo.cpp就可以了。查看最后//
部分(卸载字典)。我试图让valgrind工作,但没有,我可能没有。对于那些对我的工作感兴趣的人,就是这样的:https://cs50.harvard.edu/x/2020/psets/5/speller/
一直让我发疯!
编辑:这是我编写的100多行代码: 关于该问题,似乎是有关内存未正确释放的某种情况。似乎超时了,因为cs50附带的调试器说直到皱着眉头才能翻倒,否则无法进行检查(又可以正常工作,很好)。
// 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;
}
解决方法
您的unload()
函数没有什么问题,它可以正确释放字典中的所有节点,并将哈希表重置为所有空指针。
相反,这是代码中的其他一些问题:
- 将单词转为小写的循环遍历整个数组,但应在空终止符处停止。
- 应将
char
的{{1}}参数强制转换为tolower()
,以避免在已签名(unsigned char)
的平台上对负值进行未定义的行为。 -
char
应该将hash
计算为n
,而不是n = strlen(word)
。更好的是:您应该将循环更改为:n = strlen(word + 1)
- 在内存分配失败后,您应先关闭文件,然后再返回
for (int i = 0; word[i] != '\0'; i++)
。 -
false
格式fscanf
的缺陷在于,字典中长于"%s\n"
个字节的单词将导致目标数组溢出,从而导致未定义的行为。您可以使用长度修饰符来解决此问题:如果LENGTH
被定义为"%15s"
,则LENGTH
。 - 当
16
停止返回fscanf()
时,循环应停止。偶然地,这种特定的转换格式只能返回1
或1
,但是如果输入流中的下一个字符不能以数字开头,则EOF
将返回"%d"
。 -
0
呼叫load()
4次相同的单词。您应该只计算一次哈希码并将其存储在本地变量中。 - 不清楚函数
hash()
为什么增加全局变量size()
。