C语言双向链表调用del_node删除尾节点触发Segmentation Fault问题
问题分析
触发段错误的核心原因是仅释放了尾节点内存,但未维护双向链表的结构指针:
- 调用
del_node(list.tail)后,list.tail仍指向已被释放的内存(野指针) - 若删除的不是唯一节点,原尾节点的前一个节点
next指针仍指向失效内存,遍历链表时会访问非法地址 - 若删除的是链表最后一个节点,
list.head也会变成野指针,后续操作必然触发段错误
修复方案
必须先更新链表的结构指针,再调用del_node释放节点内存,以下两种方案任选其一:
方案1:新增专门的删除尾节点函数
添加维护链表结构的函数,复用现有del_node:
/** 删除双向链表的尾节点 */ void delete_tail(DLL_t *list) { if (!list->tail) { // 空链表直接返回 printf("list is empty, nothing to delete\n"); return; } student_t *old_tail = list->tail; if (list->head == list->tail) { // 链表仅一个节点 list->head = list->tail = NULL; } else { // 链表有多个节点 list->tail = old_tail->prev; // 更新tail为前一个节点 list->tail->next = NULL; // 新尾节点的next置空 } del_node(old_tail); // 释放旧尾节点内存 }
修改switch的case 2分支:
case 2: delete_tail(&list); break;
方案2:直接在case分支中完善逻辑
若不想新增函数,可直接修改case 2的代码:
case 2: if (!list.tail) { printf("list is empty, nothing to delete\n"); break; } student_t *old_tail = list.tail; if (list.head == list.tail) { list.head = list.tail = NULL; } else { list.tail = old_tail->prev; list.tail->next = NULL; } del_node(old_tail); break;
关键注意事项
- 必须先判断链表是否为空,避免对NULL指针操作
- 处理唯一节点时,要同时将
head和tail置为NULL - 严格遵循「保存旧节点→更新链表指针→释放旧节点」的顺序
内容的提问来源于stack exchange,提问作者jian
相关产品推荐
相关产品推荐

