哈希表内存释放报错原因排查及解决方法咨询
哈希表初始化与内存释放崩溃问题分析
问题背景
我正在自学C语言(非院校学习),学习过程中尝试实现哈希表数据结构,但遇到了内存释放崩溃的问题。以下是可复现代码:
#include <stdio.h> #include <stdlib.h> struct table_item { char *name; char gender; char *birthdate; char *address; }; struct list_node { struct table_item *data; struct list_node *next; unsigned long long hash_key; }; struct hashtable { int table_size; int num_entries; struct list_node **entries; }; struct hashtable* init_hashtable(int size); void free_hashtable(struct hashtable *table); int main(void) { struct hashtable *hashtable = NULL; int size_entry = 0; printf("Input hashtable array size: "); while (size_entry < 1) { scanf(" %d", &size_entry); } hashtable = init_hashtable(size_entry); free_hashtable(hashtable); return 0; } struct hashtable* init_hashtable(int size) { struct hashtable* new_table; if ((new_table = malloc(sizeof(struct hashtable))) == NULL) { perror("Error: failed to allocate memory for hash table\n"); exit(EXIT_FAILURE); } new_table->table_size = size; new_table->num_entries = 0; if ((new_table->entries = malloc(size*sizeof(struct list_node))) == NULL) { perror("Error: failed to allocate memory for hash table array\n"); exit(EXIT_FAILURE); } return new_table; } void free_hashtable(struct hashtable *table) { for (int i = 0; i < table->table_size; i++) { if (table->entries[i] != NULL) { free_list(table->entries[i]); table->entries[i] = NULL; } } free(table->entries); free(table); }
运行程序时,即使未向哈希表添加任何数据,调用free_hashtable释放内存时总会崩溃。通过GDB调试发现,free_hashtable的for循环中if (table->entries[i] != NULL)条件总会触发(比如i=0时),导致free_list函数尝试释放非法内存,进而产生栈转储。看起来table->entries[i]并非NULL,而是无效的struct list_node*值,导致条件被错误触发。
我原本希望通过该循环遍历entries数组,仅释放已malloc分配的节点内存,但目前程序会直接崩溃,不知道该如何修改才能达到预期效果。
问题原因分析
- malloc内存未初始化:
init_hashtable中用malloc分配的entries数组,不会自动将内存初始化为NULL,数组元素都是随机垃圾值。这些垃圾值大概率非NULL,导致if条件误判,触发非法内存释放操作。 - 内存分配类型不匹配:
struct hashtable的entries是struct list_node**(指针数组),但分配内存时用了size*sizeof(struct list_node),正确应该是size*sizeof(struct list_node*),内存分配大小错误会加剧非法访问问题。
修复方案
修正内存分配大小
在init_hashtable中,将entries的分配代码改为:if ((new_table->entries = malloc(size * sizeof(struct list_node*))) == NULL) { perror("Error: failed to allocate memory for hash table array\n"); exit(EXIT_FAILURE); }因为
entries是指针数组,每个元素是struct list_node*类型,需分配对应指针大小的空间。初始化数组元素为NULL
分配完entries后,将所有元素初始化为NULL,确保后续判断逻辑准确:- 方法一(需包含
<string.h>头文件):memset(new_table->entries, 0, size * sizeof(struct list_node*)); - 方法二:
for (int i = 0; i < size; i++) { new_table->entries[i] = NULL; }
- 方法一(需包含
补充
free_list函数实现
原代码仅声明了free_list未实现,需补充完整以正确释放链表节点及内部数据:void free_list(struct list_node *node) { struct list_node *temp; while (node != NULL) { temp = node; node = node->next; // 释放table_item内的动态分配内存 free(temp->data->name); free(temp->data->birthdate); free(temp->data->address); free(temp->data); // 释放table_item结构体 free(temp); // 释放链表节点 } }同时在代码开头添加函数声明:
void free_list(struct list_node *node);。
内容的提问来源于stack exchange,提问作者A-PSquestions
相关产品推荐
相关产品推荐

