在实现单链表时,我遇到了一个似乎很奇怪的问题。我调用list_destroyer并将指针传递给列表的头部,但是当方法返回时,传递的指针仍然指向完整列表。我不相信我已经在任何地方传递了一个结构。
这是我的结构列表和typedef
typedef struct list list_t
struct list{
void* datum;
list_t* next;
};
这是导致问题的代码
void list_destroy(list_t *head){
list_t *destroy = head;
while(head){
//printf("%d \n", list_size(head));
head = head->next;
free(destroy);
destroy = head;
}
//printf("%d \n", list_size(head));
head = NULL;
//printf("%d \n", list_size(head));
}
list_size函数已被注释掉,因为它们不是必需的,但我用它们来查看代码的输出。 printf输出显示大小正在减小。两个printf围绕着“head = NULL;”声明都打印大小为零。这也通过gdb确认。但是,当我有这个代码(跟随)调用list_destroy时,传递的指针没有改变。
int main(){
list_t *test = NULL;
int a = 1;
int b = 2;
list_append(test,&a);
list_append(test,&b);
printf("%d \n", list_size(test));
list_destroy(test);
printf("%d \n", list_size(test));
}
我仍然将list_destroy上方和下方的printf都输出到两个输出2.我没有在任何地方初始化一个新的list_t,所以我看不到list_destroy之后的printf如何仍然输出2,(特别是当printf时)在list_destroy中,传入的list_t *最后的大小为0。
答案 0 :(得分:3)
但是当方法返回时,传递的指针仍指向一个完整列表。
这是不正确的:当函数返回时,指针指向曾经是完整列表的内容。有可能,您的系统会让您不间断地遍历整个列表。但是,在调用之后取消引用此指针是未定义的行为,因此相同的代码可能会在其他系统上崩溃。
问题有一个名称 - head
成为悬空指针。
修复问题很简单 - 将指针传递给指针,并在完成时将其设置为NULL
:
void list_destroy(list_t **headPtr){
list_t *head = *headPtr;
list_t *destroy = head;
while(head){
head = head->next;
free(destroy);
destroy = head;
}
*headPtr = NULL;
}