C语言ft_lstclear函数异常:为何某版本无法正常清理链表?
链表清理函数ft_lstclear的问题分析
我正在实现用于清理链表的ft_lstclear函数,功能是通过ft_lstdelone函数释放链表元素及结构体的next指针。但遇到问题:下方第一个代码版本无法正常工作,第二个版本却可以正常运行,请问原因是什么?
无法正常工作的代码
void ft_lstclear(t_list **lst, void (*del)(void*)) { t_list *temp; t_list *begin; if (!lst || !*lst || !del) return ; begin = *lst; while (begin) { temp = (begin)->next; ft_lstdelone((begin), del); (begin) = temp; } }
可以正常工作的代码
void ft_lstclear(t_list **lst, void (*del)(void*)) { t_list *begin; if (!lst || !*lst) return ; while (*lst != NULL) { begin = (*lst)->next; ft_lstdelone((*lst), del); (*lst) = begin; } }
问题原因分析
两个版本的核心差异在于是否同步更新传入的链表头指针*lst:
- 第一个版本用局部变量
begin保存原链表头*lst,遍历释放所有节点后,始终没有修改*lst的指向。函数执行完毕后,调用者手中的链表头指针仍然指向已经被释放的内存(野指针),后续对该指针的任何操作都会触发未定义行为,比如程序崩溃、内存访问错误等。 - 第二个版本每次循环直接操作
*lst:先保存下一个节点的地址,释放当前节点后,将*lst更新为下一个节点。循环结束时,*lst会被置为NULL,调用者的链表头指针被正确置空,彻底避免了野指针问题。
另外补充:第一个版本的参数检查包含!del判断,第二个版本没有,但这不是导致第一个版本失效的核心原因——只要del有效,第一个版本依然会出现野指针问题;如果del为空,第一个版本直接返回,第二个版本会尝试调用ft_lstdelone触发错误,但用户描述的场景中del应该是有效的,因此核心问题还是链表头指针未更新。
内容的提问来源于stack exchange,提问作者VictordeLeusse
相关产品推荐
相关产品推荐

