Valgrind提示blocks are still reachable内存泄漏该如何解决?
内存泄漏原因
核心问题出在自定义的链表释放函数free_list逻辑存在错误,仅释放了链表的尾节点,其余所有节点都没有被正确释放:
你当前的free_list执行逻辑如下:
- 若传入节点为空,直接返回
- 若传入节点是尾节点(
next为NULL),释放该节点后返回 - 若传入节点不是尾节点,仅递归处理下一级节点,完全没有释放当前节点
这就导致除了每个哈希桶的链表尾节点外,其余所有你在load函数里通过malloc申请的节点都没有被释放,Valgrind检测到这些节点还被全局哈希表table的指针指向,所以归类为still reachable类型的内存泄漏。
修复方案
直接修正free_list的释放逻辑即可,遵循「先释放后继链表,再释放当前节点」的递归释放规则,修改后代码如下:
bool free_list(node *w) { if (w == NULL) { return true; } // 先递归释放当前节点的后续所有节点 free_list(w->next); // 再释放当前节点本身 free(w); return true; }
如果担心链表过长导致递归栈溢出,也可以换成迭代版本的实现,性能和稳定性更好:
bool free_list(node *w) { node *curr = w; while (curr != NULL) { node *next_node = curr->next; free(curr); curr = next_node; } return true; }
可选优化
你当前的load函数仅在读取到换行符时才会将暂存的单词插入哈希表,如果加载的字典文件最后一个单词末尾没有换行符,会导致最后一个单词丢失,你可以在load函数的fclose(dict)之前补充如下逻辑处理该情况:
// 处理字典末尾无换行的最后一个单词 if (index > 0) { tmp[index] = '\0'; node *n = malloc(sizeof(node)); if (n == NULL) { unload(); fclose(dict); return false; } n->next = table[hash(tmp)]; strcpy(n->word, tmp); table[hash(tmp)] = n; word_count += 1; }
内容的提问来源于stack exchange,提问作者Son Phan
相关产品推荐
相关产品推荐

