CS50 Speller程序出现Segmentation Fault,请求定位错误原因
CS50 Speller 段错误排查
核心错误原因
你的代码里直接触发段错误的是load函数中的char *word = NULL;:
fscanf(infile, "%s", word)需要一个有效的内存地址来存储读取的单词,但你将word初始化为NULL,未分配任何内存空间。当fscanf尝试往空指针指向的区域写入数据时,直接引发内存访问违规,也就是段错误。
附带问题及修复方案
哈希表节点覆盖问题
当前代码处理哈希值相同的单词时,会直接用新节点覆盖table[hash_value]的旧值,导致之前的节点内存泄漏,且同一个哈希桶仅能保留最后一个单词。正确做法是用链表串联同哈希值的节点:
首先修改node结构体,添加链表指针:typedef struct node { char word[LENGTH + 1]; struct node *next; // 新增链表指针 } node;然后在
load函数中替换table[hash_value] = new_node;为:new_node->next = table[hash_value]; // 先指向当前桶的头节点 table[hash_value] = new_node; // 将新节点设为桶的头节点check函数逻辑错误
当前check仅检查哈希桶是否为空,未遍历链表查找具体单词,且未实现大小写不敏感的检查要求。修正后的逻辑:bool check(const char *word) { char lower_word[LENGTH + 1]; // 将输入单词转为小写 for (int i = 0; word[i] != '\0'; i++) { lower_word[i] = tolower(word[i]); } lower_word[strlen(word)] = '\0'; unsigned int hash_val = hash(lower_word); node *cursor = table[hash_val]; // 遍历链表查找单词 while (cursor != NULL) { if (strcmp(lower_word, cursor->word) == 0) { return true; } cursor = cursor->next; } return false; }hash函数的溢出与大小写问题
原哈希计算hash_value = word[i] * hash_value易引发无符号整数溢出,且未处理大小写导致同一单词大小写不同哈希值不同。优化后的哈希函数:unsigned int hash(const char *word) { unsigned int hash_value = 0; for (int i = 0; word[i] != '\0'; i++) { hash_value = hash_value * 31 + tolower(word[i]); // 用31作为乘数,转小写保证哈希不区分大小写 } return hash_value % N; }
修复段错误的关键步骤
将load函数中的char *word = NULL;替换为:
char word[LENGTH + 1]; // 直接分配足够存储最长单词的栈内存,LENGTH为CS50定义的常量
这样fscanf就有了合法的内存地址存储读取的单词,解决段错误的核心问题。
内容的提问来源于stack exchange,提问作者DreamTheCasual
相关产品推荐
相关产品推荐

