【发布时间】:2022-01-15 23:49:13
【问题描述】:
我正在使用 CS50 pset5 拼写器,但我不断收到分段错误错误。 Debug50 表明问题出在load 函数的实现中的n->next = table[index]; 行,第110 行。我试图修改,但我不知道为什么它会出错。在我的代码下面,有人可以帮助我吗?
// Implements a dictionary's functionality
#include <stdbool.h>
#include <strings.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.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 = 150000;
// Nodes counter
int nodes_counter = 0;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO
int hash_value = hash(word);
node *cursor = malloc(sizeof(node));
if (cursor != NULL)
{
cursor = table[hash_value];
}
if (strcasecmp(cursor->word, word) == 0) // If word is first item in linked list
{
return 0;
}
else // Iterate over the list by moving the cursor
{
while (cursor->next != NULL)
{
if (strcasecmp(cursor->word, word) == 0) // If word is found
{
return 0;
}
else
{
cursor = cursor->next;
}
}
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// Adaptation of FNV function, source https://www.programmingalgorithms.com/algorithm/fnv-hash/c/
const unsigned int fnv_prime = 0x811C9DC5;
unsigned int hash = 0;
unsigned int i = 0;
for (i = 0; i < strlen(word); i++)
{
hash *= fnv_prime;
hash ^= (*word);
}
return hash;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// Open Dictionary File (argv[1] or dictionary?)
FILE *file = fopen(dictionary, "r");
if (file == NULL)
{
printf("Could not open file\n");
return 1;
}
// Read until end of file word by word (store word to read in word = (part of node)?)
char word[LENGTH + 1];
while(fscanf(file, "%s", word) != EOF)
{
// For each word, create a new node
node *n = malloc(sizeof(node));
if (n != NULL)
{
strcpy(n->word, word);
//Omitted to avoid segmentation fault n->next = NULL;
nodes_counter++;
}
else
{
return 2;
}
// Call hash function (input: word --> output: int)
int index = hash(word);
// Insert Node into Hash Table
n->next = table[index];
table[index] = n;
}
return false;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// Return number of nodes created in Load
if (nodes_counter > 0)
{
return nodes_counter;
}
return 0;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
for (int i = 0; i < N; i++)
{
node *cursor = table[i];
while (cursor->next != NULL)
{
node *tmp = cursor;
cursor = cursor->next;
free(tmp);
}
}
return false;
}
【问题讨论】:
-
-fsanitize=address擅长调试这些。 -
在
check函数node *cursor = malloc(sizeof(node));后面跟cursor = table[hash_value];是内存泄漏。如果table[hash_value]为 NULL,则函数中的所有其余代码都使用 NULL 指针。您不需要在该函数内分配任何内容。从表中获取条目,如果它不是 NULL,则检查是否找到该单词,否则返回 false。 -
也不能保证
hash函数将返回一个小于 150000 的值,因此您会越界访问数组。你需要像int hash_value = hash(word) % N ;这样的东西来强制它不是正确的范围。您需要在使用hash函数的返回值的任何地方执行此操作。 -
在你的
hash函数中,虽然你用i循环word的长度,你实际上并没有使用i来索引word,所以你只是使用word的第一个字符一遍又一遍。而不是hash ^= (*word);,我想你想要hash ^= word[i];。
标签: c linked-list segmentation-fault hashtable cs50