DestroyList是否存在问题?

来源:8-6 案例:单链表的基本实现

慕盖茨3428307

2025-01-30

老师,您好。
注意到您的DestroyList代码如下:

void DestroyList(ListNode **head) {
  if (!head || !(*head)) return;

  ListNode *current = *head;
  while (current) {
    ListNode *to_be_destroy = current;
    current = current->next;
    DestroyNode(&to_be_destroy);
  }

  *head = NULL;
}

您在讲课时,提到“需要将*head置为NULL,这样外部就知道链表已经被销毁了”。可是我观察DestroyNode的代码:

void DestroyNode(ListNode **node_ptr) {
  (*node_ptr)->next = NULL;
  free(*node_ptr);
  *node_ptr = NULL;
}

其中*node_ptr = NULL;已经在尝试做类似的事情了,理论上每个Node的指针都会置为Null。
于是我注释掉DestroyList中的*head = NULL;,却发现链表似乎没有被成功删除,head仍然指向了一段地址。
我进一步分析后,发现问题可能出现在DestroyList的这一行代码中:

ListNode *to_be_destroy = current;

在这里发生了复制,这导致调用DestroyNode时,虽然to_be_destroy指向的内存被释放了,但是DestroyNode中的*node_ptr = NULL;却失效了,因为真正置为NULL的是复制出来的、新的to_be_destroy指针,而非我们希望的指针。

最后,我做了如下修改,发现每个Node的指针都如设想的那样被置为Null了。

void DestroyList(ListNode **head) {
  if (!(head) || !(*head))
    return;
  ListNode **current = head;
  while (*current) {
    ListNode **to_be_destroy = current;
    current = &(*current)->next;
    DeleteNode(to_be_destroy);
  }
//  *head = NULL;
}

请问我的分析和修改是否正确?

写回答

1回答

bennyhuo

2025-01-30

分析没问题,就这个案例来讲,修改的运行结果看上去也正确。

不过,实践中不建议这样处理,因为明显程序复杂了不少。这里的关键点在于链表(n个节点)和一个节点的表示形式相同导致,如果再进一步做抽象,把链表的类型也定义出来,就不会有这种疑问了。
0
0

C语言系统化精讲 重塑编程思想 打造坚实的开发基础

如果通向大牛的道路有捷径,那就是先学好C语言

2208 学习 · 853 问题

查看课程