销毁链表,为什么这有效?

时间:2018-01-27 16:45:59

标签: c linked-list valgrind

我创建了这个破坏链表的函数,head是链表的头部。

void destroy(node** head){

    node* current = NULL;
    while(*head != NULL){
        current = *head;
        free(current);
        *head = (*head)->next;
    }

}

我认为此代码不起作用,因为headcurrent指向内存中的相同地址,并且由于它已被释放,因此您无法访问(*head)->next。但是当我运行该程序时它运行正常,当我检查列表是空的。

我甚至在程序上运行了valgrind测试,没有内存泄漏,尽管几乎没有神秘错误。

为什么这段代码有效?它似乎不直观。

4 个答案:

答案 0 :(得分:3)

  

我认为此代码无法正常工作,因为*headcurrent指向内存中的相同地址,并且由于它已被释放,因此无法访问{{1 }}

这完全正确:一旦(*head)->next free(current)访问未定义的行为

不幸的是,未定义的行为并不等同于崩溃,因此人们可能会觉得程序正在运行;它不是!

  

我甚至在程序上运行了valgrind测试,没有内存泄漏,尽管几乎没有神秘错误。

这不是内存泄漏,而是访问释放的内存。它确实会产生一些含糊不清的错误信息 - 这些内容如下:

  

地址(*head)->next是16个空闲' d

块内的4个字节

这意味着0x5a02048为16,sizeof(node)的偏移为4。

显然,释放列表的正确方法是交换访问next的行并调用next

free(current)

请注意,while(*head != NULL){ node* current = *head; *head = (*head)->next; free(current); } 可以在循环内声明。

答案 1 :(得分:1)

代码具有未定义的行为,因为您访问的内存只有free' d。

未定义行为的真正坏处在于,即使代码具有未定义的行为,可能会出现

将代码更改为:

void destroy(node** head){   
    node* current = NULL;
    while(*head != NULL){
        current = *head;
        *head = (*head)->next;
        free(current);
    }
}

以便在致电*head

之前更改free

答案 2 :(得分:0)

这很有效,因为在这种特殊情况下,释放的内存没有被修改,即使它是免费的,你也不再拥有它。

不要这样做。在另一个编译器或平台上,它可能会被修改,或者可能会发生非法的内存访问错误,或者你可能会更改程序另一部分使用的内存。这使得这是一个糟糕的方法。只使用程序拥有的内存,

答案 3 :(得分:0)

这是我的解决方案:

void destroy(node** head){   
                node* current = *head;
                while((*head) != NULL){
                        if((*head)->next!=NULL)
                                *head = (*head)->next;
                        else { /* if next node is NULL, free it and comes out of loop or function  **/
                                (*head) = NULL;
                                free(current);
                                current = NULL;/* to avoid Dangling pointer problem **/
                                break;//or return bcz there will not be further node to delete **/
                        }
                        /** below 2 statements will execute only if part is true **/
                        free(current);
                        current = *head;
                }
        }