为什么我的节点都没有被释放?(cs50 pset5分段故障)C
我在哈佛cs50课程的pset5中实现加载和卸载函数时遇到问题。当我运行它时,我得到一个分段错误,当我运行valgrind时,它告诉我在加载时malloc的所有节点都没有被释放 几天来我一直在尝试解决这个问题,我尝试了几种不同的卸载函数实现,但都没有效果。我想错误可能在我的加载函数中。谁能帮我拿这个吗为什么我的节点都没有被释放?(cs50 pset5分段故障)C,c,memory-leaks,segmentation-fault,cs50,C,Memory Leaks,Segmentation Fault,Cs50,我在哈佛cs50课程的pset5中实现加载和卸载函数时遇到问题。当我运行它时,我得到一个分段错误,当我运行valgrind时,它告诉我在加载时malloc的所有节点都没有被释放 几天来我一直在尝试解决这个问题,我尝试了几种不同的卸载函数实现,但都没有效果。我想错误可能在我的加载函数中。谁能帮我拿这个吗 /**************************************************************************** * dictionary.c *
/****************************************************************************
* dictionary.c
*
* Computer Science 50
* Problem Set 5
*
* Implements a dictionary's functionality.
***************************************************************************/
#include <stdbool.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "dictionary.h"
#define HASHTABLE_SIZE 5000
// create word counter for size
int wordCount = 0;
// linked link struct
typedef struct node
{
// word's length + NULL character
char word[LENGTH + 1];
struct node* next;
}
node;
// Hashtable array
node* hashtable[HASHTABLE_SIZE];
// hash function from study.cs50.net
int hash_function(char* key)
{
// initialize index to 0
int index = 0;
// sum ascii values
for (int i = 0; key[i] != 0; i++)
{
index += toupper(key[i]) - 'A';
}
return index % HASHTABLE_SIZE;
}
/**
* Returns true if word is in dictionary else false.
*/
bool check(const char* word)
{
// create variable to hold word
char temp[LENGTH + 1];
// convert every character in word to lowercase
for (int i = 0, n = strlen(word); i < n; i++)
{
if (isalpha(word[i]))
{
temp[i] = tolower(word[i]);
}
}
// get hashed word's index
int hash_index = hash_function(temp);
// find head of that index
node* head = hashtable[hash_index];
// traverse through linked list
for (node* cur = head; cur != NULL; cur = cur->next)
{
// find if linnked list contains word
if (strcmp(cur->word, word) == 0)
{
return true;
}
}
return false;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
// // open file
FILE* file = fopen(dictionary, "r");
// check if file exists
if (file == NULL)
{
return false;
}
// word length plus NULL character
char word[LENGTH + 1];
// iterate through every word of the dictionary
while (fscanf(file, "%s\n", word) != EOF) // Source: http://stackoverflow.com/questions/6275558/question-about-whileeof
{
node* new_node = malloc(sizeof(node));
if (new_node == NULL)
{
return false;
}
wordCount++;
strcpy(new_node->word, word); // Source: cs50 reddit
int hash_index = hash_function(new_node->word);
// check whether node should be head
if (hashtable[hash_index] == NULL)
{
hashtable[hash_index] = new_node;
new_node->next = NULL;
}
else
{
new_node->next = hashtable[hash_index];
hashtable[hash_index] = new_node;
}
}
// close file
fclose(file);
return false;
}
/**
* Returns number of words in dictionary if loaded else 0 if not yet loaded.
*/
unsigned int size(void)
{
return wordCount;
}
/**
* Unloads dictionary from memory. Returns true if successful else false.
*/
bool unload(void)
{
// go through all of the indexes in the hashtable
for (int i = 0; i < HASHTABLE_SIZE; i++)
{
node* head = hashtable[i];
while (head != NULL)
{
node* ptr = head->next;
free(head);
head = ptr;
}
}
return true;
}
/****************************************************************************
*字典
*
*计算机科学50
*习题集5
*
*实现字典的功能。
***************************************************************************/
#包括
#包括
#包括
#包括
#包括
#包括
#包括“dictionary.h”
#定义哈希表大小5000
//为大小创建单词计数器
int字数=0;
//链接结构
类型定义结构节点
{
//单词长度+空字符
字符字[长度+1];
结构节点*下一步;
}
节点;
//哈希表数组
节点*哈希表[哈希表大小];
//study.cs50.net中的哈希函数
int散列函数(字符*键)
{
//将索引初始化为0
int指数=0;
//ascii值总和
对于(int i=0;键[i]!=0;i++)
{
索引+=toupper(键[i])-‘A’;
}
返回索引%HASHTABLE\u大小;
}
/**
*如果单词在字典中,则返回true,否则返回false。
*/
布尔检查(常量字符*单词)
{
//创建用于保存word的变量
字符温度[长度+1];
//将word中的每个字符转换为小写
for(int i=0,n=strlen(word);inext)
{
//查找链接列表是否包含word
if(strcmp(cur->word,word)==0)
{
返回true;
}
}
返回false;
}
/**
*将字典加载到内存中。如果成功,则返回true;否则返回false。
*/
布尔加载(常量字符*字典)
{
////打开文件
FILE*FILE=fopen(字典,“r”);
//检查文件是否存在
if(file==NULL)
{
返回false;
}
//字长加空字符
字符字[长度+1];
//反复阅读字典中的每个单词
while(fscanf(文件,“%s\n”,word)!=EOF)//来源:http://stackoverflow.com/questions/6275558/question-about-whileeof
{
node*new_node=malloc(sizeof(node));
if(新节点==NULL)
{
返回false;
}
字数++;
strcpy(new_node->word,word);//来源:cs50 reddit
int hash_index=hash_函数(新节点->单词);
//检查节点是否应为头部
if(哈希表[哈希索引]==NULL)
{
哈希表[哈希索引]=新的\u节点;
新建节点->下一步=空;
}
其他的
{
新建节点->下一步=哈希表[哈希索引];
哈希表[哈希索引]=新的\u节点;
}
}
//关闭文件
fclose(文件);
返回false;
}
/**
*如果已加载,则返回字典中的字数;如果尚未加载,则返回0。
*/
无符号整数大小(void)
{
返回字数;
}
/**
*从内存中卸载字典。如果成功,则返回true;否则返回false。
*/
bool卸载(无效)
{
//检查哈希表中的所有索引
for(int i=0;inext;
自由(头);
水头=ptr;
}
}
返回true;
}
您的卸载功能良好。代码的问题在于check
功能,尤其是您试图将输入转换为小写的部分:
char temp[LENGTH + 1];
for (int i = 0, n = strlen(word); i < n; i++)
{
if (isalpha(word[i]))
{
temp[i] = tolower(word[i]);
}
}
chartemp[长度+1];
for(int i=0,n=strlen(word);i
这里有两个问题。首先,temp
不是以null结尾的。其次,检查isalpha
意味着您可以不初始化字符:如果您的输入是,比如说,“我”
,temp
将保存'I'
,垃圾,'m'
,垃圾,当它应该保存'I'
,'m'
,'0'
,垃圾
或者,您可以过滤掉不需要的字符。在这种情况下,您需要两个索引:一个用于源单词,另一个用于过滤单词
但您甚至不需要这个额外的步骤,因为哈希函数再次将输入转换为toupper
说到你的散列函数:你可能想选择一个更好的。当前的一个不能很好地将值分布在5000个插槽上。(当你在0到25之间添加最多20个数字时,你怎么能达到5000?)
散列还有另一个问题:如果您输入一个数字,则贡献的“字母”为负数,因为在ASCII中,数字的值为48到57,您从中减去'a'
,65的值。通常,哈希函数应该返回一个无符号值。在调试器下运行此函数时,您发现了什么?“free”的点击次数是否与“malloc”的点击次数相同?请显示您的main
函数和/或驱动整个程序的其他代码。否则,我们甚至不知道您是否正在调用unload
(我并不是说您没有,但在StackOverflow上,简单的错误并不少见)