CS50 Pset5 speller.c中load函数出现Segmentation Fault求助
CS50 Pset5 load函数段错误原因分析
我正在完成CS50的Pset5作业,实现第一个需要完成的load()函数时遇到问题。load函数需要从“dictionary”文件加载所有字符串,加载成功返回true,出现内存不足等问题则返回false。完成函数编写后,编译运行出现Segmentation Fault(段错误),无法定位问题。以下是我的代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <stdbool.h> #include "dictionary.h" typedef struct node { char word[LENGTH + 1]; struct node *next; } node; const unsigned int N = 26; node *table[N]; // Hashes word to a number unsigned int hash(const char *word) { int i = toupper(word[0]) - 'A'; return i; } // Loads dictionary into memory, returning true if successful, else false bool load(const char *dictionary) { // Allocate temporary memory char *tmp = malloc(LENGTH + 1); if (tmp == NULL) { printf("Could not open file\n"); return false; } // Open file FILE *d = fopen(dictionary, "r"); if (d == NULL) { printf("Could not open file\n"); return false; } // Until EOF: create new node, point new node to table[key] -> next, point table[key] to new node. while (fscanf(d, "%s", tmp) != EOF) { node new; int key = hash(tmp); strcpy(new.word, tmp); new.next = table[key] -> next; table[key] -> next = &new; } free (tmp); return true; }
段错误的核心原因:
- 栈节点的非法引用:循环内定义的
node new是栈上的局部变量,每次循环结束后该变量的内存会被系统回收,但你把它的地址&new存入了链表指针。后续访问这个地址时,内存已经不属于当前节点,属于非法内存访问,直接触发段错误。必须用malloc在堆上分配节点内存:node *new_node = malloc(sizeof(node)); if (new_node == NULL) { fclose(d); free(tmp); return false; } - NULL指针解引用:全局哈希表
table[N]默认初始化为NULL,你直接访问table[key]->next,相当于对NULL指针进行解引用操作,这也是引发段错误的关键原因。正确的链表插入逻辑应该是:// 插在链表头部 new_node->next = table[key]; table[key] = new_node; - 错误提示混淆:内存分配失败时打印的是"Could not open file",和文件打开失败的提示重复,应该改为"Memory allocation failed"之类的准确提示,避免调试时混淆问题点。
内容的提问来源于stack exchange,提问作者Freddy
相关产品推荐
相关产品推荐

