C语言哈希表加载字典时内存泄漏问题排查求助
内存泄漏问题修复及代码优化建议
我一眼就看到了你的内存泄漏根源——unload函数里的提前返回导致大部分节点没被释放!
问题分析
看你当前的unload代码:
bool unload(void) { for (int i = 0; i < N; i++) { node *cursor = table[i]; while (cursor != NULL) { node *temp = cursor; cursor = cursor -> next; free(temp); } return true; // 这里是致命错误! } return false; }
你在for循环的第一次迭代(也就是处理完哈希表第一个桶之后)就直接return true了,剩下的499999个桶里的所有字典节点都完全没被释放,这就是Valgrind显示“143,091 blocks are still reachable”的原因。
修复后的unload函数
把return true移到for循环外面,确保所有桶的节点都被释放:
bool unload(void) { // 遍历哈希表的每一个桶 for (int i = 0; i < N; i++) { node *cursor = table[i]; while (cursor != NULL) { node *temp = cursor; cursor = cursor->next; free(temp); } } // 所有节点都释放完成后再返回成功 return true; }
额外的代码优化建议
除了内存泄漏,你的代码还有两个潜在问题可以优化:
- check函数的字符串越界问题
你在check里定义char lower_case[strlen(word)];,但strlen返回的长度不包含字符串终止符\0,strcpy的时候会导致数组越界,应该改成:int len = strlen(word); char lower_case[len + 1]; // 多留一个位置存'\0' - check函数的冗余循环
你已经通过哈希函数拿到了对应的桶索引,完全不需要外层的for (int i = 0; i < N; i++)循环,这个循环会让你重复遍历所有链表N次,严重浪费性能,直接遍历目标索引的链表即可。
优化后的check函数:
bool check(const char *word) { int len = strlen(word); char lower_case[len + 1]; strcpy(lower_case, word); for(int i = 0; i < len; i++) { // 转成unsigned char避免tolower处理负数字符的未定义行为 lower_case[i] = tolower((unsigned char)lower_case[i]); } unsigned int index = hash(lower_case); node *cursor = table[index]; // 直接遍历目标桶的链表 while (cursor != NULL) { if (strcasecmp(cursor->word, lower_case) == 0) { return true; } cursor = cursor->next; } return false; }
修复后再用Valgrind检测,内存泄漏应该就消失了!
内容的提问来源于stack exchange,提问作者snowboly
相关产品推荐
相关产品推荐

