CS50 Pset5 Speller:Valgrind内存检测失败问题求助
CS50 Speller作业Valgrind内存可达问题排查
你的Valgrind检测到的56字节可达内存,根源在于unload函数的逻辑错误,同时load函数还存在潜在的内存泄漏风险,具体分析和修复方案如下:
问题1:unload函数提前返回,未释放所有哈希桶内存
你的unload函数在处理完第一个哈希桶(i=0)后,只要cursor为NULL就直接return true,导致后续N-1个哈希桶完全没有被遍历和释放。这些未处理的哈希桶里的节点内存会处于可达但未释放的状态,正好对应Valgrind的报错。
问题2:load函数中途malloc失败时未清理已分配内存
如果load过程中某个节点的malloc失败,你直接return false,但此前已经成功分配的节点没有被释放,打开的字典文件也没有关闭,会造成内存泄漏。
修复方案
1. 修正unload函数,遍历所有哈希桶后再返回
bool unload(void) { for (int i = 0; i < N; i++) { node *cursor = table[i]; while (cursor) { node *tmp = cursor; cursor = cursor->next; free(tmp); } // 移除此处的return,确保所有桶都被处理 } // 所有哈希桶处理完成后再返回成功 return true; }
2. 修复load函数的内存泄漏问题
当malloc失败时,先释放已分配的所有节点,关闭文件后再返回:
bool load(const char *dictionary) { FILE *file = fopen(dictionary, "r"); if (file == NULL) { printf("Unable to open %s\n", dictionary); return false; } char word[LENGTH + 1]; // 显式初始化全局变量,避免未定义行为 word_count = 0; while (fscanf(file, "%s", word) != EOF) { node *n = malloc(sizeof(node)); if (n == NULL) { // 清理已分配的所有节点 for (int i = 0; i < N; i++) { node *cursor = table[i]; while (cursor) { node *tmp = cursor; cursor = cursor->next; free(tmp); } table[i] = NULL; } fclose(file); word_count = 0; return false; } strcpy(n->word, word); hash_value = hash(word); n->next = table[hash_value]; table[hash_value] = n; word_count++; } fclose(file); return true; }
额外提示:全局变量word_count最好在load开头显式初始化为0,避免程序启动时的未定义初始值影响size函数的准确性。
内容的提问来源于stack exchange,提问作者Pediramm
相关产品推荐
相关产品推荐

