为何C语言链表删除尾节点函数未置previousNode->next为NULL会出错?
链表尾节点删除的异常问题分析
问题代码
Node* deleteAtTail(Node* head) { if (head == NULL) /* If List is empty... */ { return NULL; } else /* If List has 1 item... */ if (head -> next == NULL) { free(head); return NULL; } else { Node* currentNode = head; /* Traversal Pointer */ Node* previousNode = NULL; /* Traversal Pointer */ while(currentNode -> next != NULL) { previousNode = currentNode; /* Move up previous node */ currentNode = currentNode -> next; /* Move up current node */ } previousNode -> next = NULL; /* Make previousNode the new tail */ free(currentNode); /* Delete currentNode pointer */ return head; } }
用户问题
若注释掉
previousNode -> next = NULL;这行代码,程序会陷入无限循环。请问这是为什么?我认为
head及其链表并未被修改,只是复制给了currentNode指针,且我返回的是未改动的链表。previousNode和currentNode都在函数作用域内,为何不设置previousNode的next指针为NULL程序就会失效?
问题解析
- 指针操作的是原链表内存:
currentNode和previousNode是函数内的局部指针,但它们指向的是堆上的链表节点实际内存,不是链表的副本。修改previousNode->next就是直接修改原链表的节点内容,并非操作所谓的“副本”。 - 释放内存后留下野指针:注释掉
previousNode->next = NULL后,原尾节点被free释放,但倒数第二个节点的next指针还指着这块已被释放的内存。这块内存的内容是不确定的,属于野指针范畴。 - 无限循环的触发逻辑:如果后续有遍历链表的操作(比如再次调用删除尾节点、打印链表),当遍历到倒数第二个节点时,
next指向的野指针内存里的值可能不是NULL,导致遍历的while循环条件currentNode->next != NULL永远成立,直接陷入无限循环。 - 返回head不解决问题:
head确实没被修改,但链表的结构已经被破坏——倒数第二个节点的next是非法指针,返回的head只是指向一个有缺陷的链表起始地址而已。
内容的提问来源于stack exchange,提问作者BMAGS
相关产品推荐
相关产品推荐

