哈希表insert_el函数报错排查:是否与free_ht实现有关?
你的insert_el错误并非由free_ht导致,但两者均存在bug
free_ht函数的问题
你的free_ht有两个致命错误:
- 错误释放对象:
free(&ht[j]);是完全错误的——ht[j]才是你通过calloc分配的动态内存指针,&ht[j]是指针数组元素的地址,不属于动态分配的内存范围,调用free会触发未定义行为。正确写法是free(ht[j]);。 - 语法不完整:循环和函数都缺少闭合的
},编译直接报错。
修正后的free_ht:
void free_ht(int *ht[]) { for (int j = 0; j < value; ++j) { free(ht[j]); } }
insert_el函数的错误分析(各版本)
初始版本
- 没必要用
calloc分配z,直接用栈变量即可,既浪费内存又增加泄漏风险。 - 数组长度计算逻辑完全错误:
sizeof(&ht[*z])取的是指针的字节数(通常4/8),无法获取动态数组的实际长度,导致扩容彻底失效。 - 插入逻辑混乱:遍历找0位置插入后,错误地将计数
ht[z][0]设为1,丢失了真实的元素个数记录。
第一次修改
- 改用栈变量
z是正确的,但插入时仍错误地将计数重置为1,导致之前的元素计数丢失。 - 扩容容量计算错误:忽略了计数元素占的位置,导致数组容量不足。
第二次修改
- 直接在
size位置插入元素的逻辑正确,但未更新计数ht[z][0],后续插入无法获取当前元素个数。
第三次修改(最接近正确的版本)
- 核心错误:扩容时的数组总长度计算错误。你的数组结构是
[元素个数, 元素1, 元素2,...],因此数组总长度应为元素个数 + 1。当前元素个数为size,插入后变为new_size = size + 1,此时需要的数组总长度是new_size + 1,而非你写的new_size。realloc(ht[z], new_size * sizeof(int))会导致数组容量不足,写入ht[z][size]时会触发越界访问,引发未定义行为。 - 缺失
realloc返回值检查:若内存分配失败,realloc返回NULL,直接赋值会丢失原指针,导致内存泄漏。
修正后的insert_el函数
void insert_el(int *ht[], int *x) { int z; hash_el(x, &z, value); if (ht[z][0] == 0) { ht[z][1] = *x; ht[z][0] = 1; } else { int size = ht[z][0]; int new_size = size + 1; // 数组总长度 = 新元素个数 + 1(计数位) int *new_arr = realloc(ht[z], (new_size + 1) * sizeof(int)); if (new_arr == NULL) { // 可添加内存分配失败的错误处理逻辑 return; } ht[z] = new_arr; ht[z][size] = *x; ht[z][0] = new_size; } }
内容的提问来源于stack exchange,提问作者Hannan Sandhu
相关产品推荐
相关产品推荐

