一个抽象的问题:假设我有一个单链接的节点列表:
#node 1 #node 2
root->[data|next]->[data|next]->NULL
在C中,声明了root:
struct Node *root = NULL;
其中* root是节点指针'保持'地址“NULL”。
现在,假设我要删除链表中的最后一个节点,以下代码将允许计算机执行此类操作:
//pop: pop removes last/latter node in linked list and sets new last node to NULL
void pop(struct Node *root){
struct Node *last;
struct Node *current = root; //current point to same node as root
while(current->next != NULL){
if(current->next == NULL) {break;} //premature break in traversing of linked list; will stop at last node
last = current; //last points to same node as current
current = current->next; //move current to next node
}
last->next = NULL; //point second-to-last node to NULL, making it defacto last node in list
free(current); //free last node to heap
}//end pop
调用pop并将root传递给函数后,新的链表如下所示:
#node 1
root->[data|next]->NULL
如果程序再次调用pop,我们应该期望链表看起来像这样:
root->NULL
然而,它没有!在按顺序排列整数元素的链接的情况下,我们将调用pop直到我们观察到奇怪的行为:
List: 1 2 3
Call pop
List: 1 2
Call pop
List: 1
Call pop
List 1980765
以上是由悬空指针引起的未定义行为的示例。现在的问题是:程序如何避免这种行为,并产生一个接近root-> NULL的副作用,从链表中弹出所有节点,直到所述列表为空?
答案 0 :(得分:1)
<强>首先强>
这种情况永远不会成真:
if(current->next == NULL) {break;}
如果确实如此,我们就不会达到该行,但会超出while
循环。
第二名:
如果您至少执行一次循环体,则指针last
保持未初始化状态。因此
last->next = NULL;
将随机内存位置设置为NULL
<强>第三强>
当您尝试删除最后剩余的元素时,您需要free(root)
。但是,您无法将root
设置为NULL
,因为它是按值传递的。