Speller程序手动测试正常但check50无输出、debug50崩溃求助
Speller项目问题排查与修复
问题现象
- 代码本地编译运行、手动测试全部通过,但check50测试返回
expected "MISSPELLED WOR...", not "",无错误单词输出 - valgrind检测无内存错误,但debug50中在dictionary.c的任意函数设断点会触发段错误,生成
Could not load source ./string/../sysdeps/x86_64/multiarch/strlen-evex.S': 'SourceRequest' not supported..提示 - 无断点时程序可正常执行
核心问题分析
- Hash函数未处理非字母开头的单词:当前hash函数直接取单词首字符计算索引,若单词以非字母(如 apostrophe
')开头,会得到负数索引,触发哈希表数组越界访问的未定义行为。本地字典可能无此类单词,所以手动测试正常,但check50的测试字典包含此类单词,导致哈希表损坏,check函数无法正确识别错误单词。 - Check函数遍历所有哈希桶:虽然功能上可行,但效率极低,且在哈希表损坏时容易出现误判。
修复方案
1. 修复Hash函数,处理非字母开头的单词
修改hash函数,跳过单词前的非字母字符,找到第一个有效字母后计算哈希索引,确保返回值在0到N-1范围内:
// Hashes word to a number unsigned int hash(const char *word) { int i = 0; // 跳过非字母字符,找到第一个有效字母 while (word[i] != '\0' && !isalpha((unsigned char)word[i])) { i++; } // 若单词无字母(字典中理论不存在),返回默认桶 if (word[i] == '\0') { return 0; } return tolower((unsigned char)word[i]) - 'a'; }
2. 优化Check函数,仅遍历对应哈希桶
根据单词的哈希值直接定位到对应桶,避免遍历所有桶,提升效率并减少误判:
// Returns true if word is in dictionary, else false bool check(const char *word) { unsigned int bucket = hash(word); node *trav = table[bucket]; while (trav != NULL) { if (strcasecmp(trav->word, word) == 0) { return true; } trav = trav->next; } return false; }
3. debug50段错误说明
该错误是gdb尝试读取系统库函数strlen的汇编源文件但找不到导致的,属于环境问题,与代码逻辑无关。修复代码后,功能正常时可忽略此提示,或在调试时跳过系统库函数的断点。
验证步骤
- 重新编译代码:执行
make clean && make - 本地测试:使用包含非字母开头单词的字典测试,确保功能正常
- 运行check50:验证测试用例是否通过
- debug50调试:虽然仍可能出现strlen源文件提示,但代码逻辑可正常断点调试
内容的提问来源于stack exchange,提问作者fincode
相关产品推荐
相关产品推荐

