在VSCode中编写C语言Hangman游戏时while循环出现Segmentation Fault
排查Hangman游戏代码中的段错误及修复方案
直接触发段错误的原因
代码最开头的while (fgets(buf, LEN, fp))完全是多余的,而且此时buf和fp都还没定义——这两个变量是在这个循环体内部才声明的。未初始化的fp是野指针,直接调用fgets会访问非法内存,立刻触发段错误,直接删掉这行外层循环即可。
其他潜在问题及修复要点
- 必须检查文件打开结果:
fopen可能因为文件不存在、权限问题返回NULL,后续操作野指针必然崩溃,添加检查:FILE *fp = fopen("dictionary.txt", "r"); if (fp == NULL) { perror("Failed to open dictionary"); return NULL; } - 扩容逻辑错误:原代码判断
dictionary->nval > dictionary->max才扩容,当nval等于max时数组已经满了,再添加元素会越界,改成dictionary->nval >= dictionary->max。 - strtok使用隐患:
strtok会修改原字符串,而且如果行尾没有换行符会返回整个buf,改用strcspn更安全地去除换行:buf[strcspn(buf, "\n")] = '\0'; - nval计数错误:循环结束后
dictionary->nval--完全没必要,每次循环nval已经正确自增,减1会导致少统计一个单词,直接删掉这行。 - 初始值优化:
dictionary->nval初始设为0更合理,和实际添加的单词数同步。
修复后的完整代码示例
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #define LEN 100 #define INIT 1 #define GROW 2 struct diction_t { int nval; int max; char **words; }; struct diction_t *load_dictionary() { char buf[LEN]; FILE *fp = fopen("dictionary.txt", "r"); if (fp == NULL) { perror("Failed to open dictionary"); return NULL; } struct diction_t *dictionary = malloc(sizeof(struct diction_t)); assert(dictionary); dictionary->nval = 0; dictionary->max = INIT; dictionary->words = malloc(sizeof(char *) * dictionary->max); assert(dictionary->words); int i = 0; while (fgets(buf, LEN, fp)) { buf[strcspn(buf, "\n")] = '\0'; if (dictionary->nval >= dictionary->max) { size_t new_capacity = GROW * dictionary->max; char **temp = realloc(dictionary->words, new_capacity * sizeof(char *)); assert(temp); dictionary->words = temp; dictionary->max = new_capacity; } dictionary->words[i] = malloc(strlen(buf) + 1); assert(dictionary->words[i]); strcpy(dictionary->words[i], buf); i++; dictionary->nval++; } fclose(fp); return dictionary; }
内容的提问来源于stack exchange,提问作者IV6IX
相关产品推荐
相关产品推荐

