C语言实现哈希表字典重哈希功能运行异常,求错误排查
代码存在的核心错误
错误1:新分配的桶数组未初始化
malloc申请的new_bins内存是未初始化的垃圾值,每个桶的初始指针不是NULL,后续遍历新桶链表时会触发野指针访问。需要在malloc后立刻把所有桶指针初始化为NULL。错误2:节点没有实际挂载到新桶链表上
你定义的cur2是栈上的局部变量,cur2 = cur只是修改了局部变量的值,完全没有修改新桶new_bins[new_idx]的指向,相当于所有节点都没有被挂载到新数组上,重哈希后新桶数组全是空的,之前的节点全部内存泄漏。
正确的做法是直接把节点头插或者尾插到新桶的链表上,头插效率更高不需要遍历到链表尾部:
// 头插法挂载节点,不需要遍历链表 cur->next = new_bins[new_idx]; new_bins[new_idx] = cur;
- 错误3:旧链表遍历逻辑错误
你在遍历旧桶链表时直接用cur = cur->next,但上面的头插操作会修改cur->next的指向,导致旧链表后续节点无法被正确遍历。需要在处理当前节点前先保存下一个节点的地址:
struct list *cur, *next; for(cur=D->bins[idx]; cur; cur=next) { next = cur->next; // 提前保存下一个节点地址 // 后续处理cur的逻辑 }
- 错误4:缺少malloc失败的容错处理
如果new_bins = malloc(...)分配失败返回NULL,后续操作会直接崩溃,需要加判空逻辑,分配失败时返回错误码。
修正后的重哈希函数参考
static int dict_rehash(struct dict *D) { int idx; int new_idx; unsigned int new_nbins; struct list **new_bins; struct list *cur, *next; #if DEBUG dict_debug_bin_fill(D); fprintf(stderr, "Rehashing...\n"); sleep(3); #endif new_nbins = D->nbins * 2; new_bins = malloc(new_nbins * sizeof(*D->bins)); if (new_bins == NULL) { return -1; // 内存分配失败返回错误 } // 初始化新桶所有指针为NULL for (int i = 0; i < new_nbins; i++) { new_bins[i] = NULL; } for (idx = 0; idx < D->nbins; idx++) { // 提前保存next指针,避免修改cur->next后断链 for(cur = D->bins[idx]; cur; cur = next) { next = cur->next; new_idx = cur->hash % new_nbins; // 头插法将节点挂载到新桶 cur->next = new_bins[new_idx]; new_bins[new_idx] = cur; } } free(D->bins); D->bins = new_bins; D->nbins = new_nbins; return 0; }
内容的提问来源于stack exchange,提问作者Azeem Akram
相关产品推荐
相关产品推荐

