C语言链表delete_min函数堆内存错误:释放节点后仍异常
堆内存错误修复:delete_min函数的前驱指针逻辑问题
打印“3rd round”后出现指针异常,虽已在delete_min中执行free(min_node)并将其置为NULL,但堆内存错误仍持续发生——核心问题出在delete_min函数中寻找最小值节点时的前驱指针跟踪逻辑完全错误,而非内存释放操作。
错误根源分析
原delete_min函数的搜索循环中,prev变量的更新逻辑混乱:
- 当发现更小的节点时,
prev = (prev == NULL)? head : prev->link无法正确指向最小值节点的前驱,导致后续删除操作时,prev指向的并非目标节点的前一个节点,进而破坏链表结构,引发野指针访问或内存非法操作。
修复后的delete_min函数代码
ListNode* delete_min(ListNode* head) { if (head == NULL) { printf("List is empty.\n"); return NULL; } ListNode* min_node = head; ListNode* prev_min = NULL; // 专门跟踪最小值节点的前驱 ListNode* current = head; ListNode* prev_current = NULL; // 遍历链表,寻找最小值节点及其前驱 while (current != NULL) { if (current->data.point < min_node->data.point) { min_node = current; prev_min = prev_current; // 更新为当前节点的前驱 } prev_current = current; current = current->link; } // 删除最小值节点 if (min_node == head) { // 处理头节点删除 head = head->link; } else { // 通过前驱节点跳过min_node,维护链表完整性 prev_min->link = min_node->link; } printf("OUT: %s (%d)\n\n", min_node->data.name, min_node->data.point); free(min_node); return head; }
修复说明
- 拆分原混乱的
prev变量为prev_min和prev_current,分别跟踪最小值节点的前驱和当前遍历节点的前驱,逻辑清晰无歧义。 - 遍历过程中,每当找到更小的节点,直接将
prev_min赋值为当前节点的前驱prev_current,确保删除时能正确定位到目标节点的前一个节点。 - 删除操作时,头节点直接更新
head指针;非头节点通过prev_min->link跳过min_node,保证链表结构不被破坏,从根源避免野指针和内存错误。
内容的提问来源于stack exchange,提问作者james Kim
相关产品推荐
相关产品推荐

