【问题标题】:C Doubly Circular Linked List DeletionC 双循环链表删除
【发布时间】:2020-12-03 16:14:18
【问题描述】:

我在从循环双向链表中删除时遇到问题。我尝试了这里提到的各种不同的方法,但它们都会导致某种错误。在这里,我收到一条错误消息“在 tcache 2 中检测到双重空闲”

void delete_list(Node *node)
{
        Node *pt;
        while(node != NULL){
                pt = node;
                node = node->next;
                free(pt);
        }
}

【问题讨论】:

  • @ProudFrog1337 提供重现问题的最小完整程序。
  • 这不是minimal reproducible example,但问题很明显:你有一个循环列表,你正在检查一个不存在的 NULL,最终node 循环回到以前的空闲会记忆的。将 node->prev->next 指针设置为 NULL,然后运行您的遍历。

标签: c list doubly-linked-list circular-list function-definition


【解决方案1】:

我在从循环双向链表

中删除时遇到问题

循环双向链表没有数据成员next 等于NULL 的节点。其数据成员next 中的tail 节点具有head 节点的地址。

所以如果你的列表不为空那么这个函数

void delete_list(Node *node)
{
        Node *pt;
        while(node != NULL){
                pt = node;
                node = node->next;
                free(pt);
        }
}

在它从tail 节点移动到它尝试释放两次的head 节点后调用未定义的行为。

该函数可以如下所示(无需测试)

void delete_list( Node **head )
{
    if ( *head )
    {
        Node *current = ( *head )->next;
     
        while ( current != *head )
        {
            Mode *tmp = current;
            current = current->next;
            free( tmp );
        }

        free( *head );
        *head = NULL;
    }
}

如果在 main 你有一个类似的声明

Node *head = NULL;
//...

然后函数可以像这样调用

delete_list( &head );

注意,如果将指向尾节点的指针与指向头节点的指针分开声明,则函数不会处理指向尾节点的指针。

在这种情况下,您需要再引入一种结构,例如

struct CircularList
{
    Node *head;
    Node *tail;
};

这确实定义了一个列表。并为这种类型的对象调用(修改后的)函数。

【讨论】:

  • 抱歉,我想我误解了 free 的作用。我认为它会自动将释放的值设置为空。我通过添加“node->previous->next = NULL”再次尝试,现在出现分段错误。我想这个错误来自其他地方?
  • @ProudFrog1337 我认为这是一种无效的方法。插入存储在已删除节点中的值的测试输出。
【解决方案2】:

释放双向链表中的节点不会从列表中删除该节点。

代码必须更正列表中前一个节点的'next'字段,并更正列表中下一个节点的'prev'字段,以便那些字段跳过要删除的节点,然后可以删除要删除的节点传递给free()

【讨论】:

    【解决方案3】:
    void delete_list(Node **head){
            Node *current, *garbage;
    
            if (*head==NULL) return; else current=(*head)->next;
    
            while(current != *head){
                    garbage=current;
                    current = current->next;
                    free(garbage);
            }
    
            free(current);
            *head=NULL;
    }
    

    【讨论】:

    • node->prev->next=NULL; 风险node->prev->nextNULL
    猜你喜欢
    • 1970-01-01
    • 2020-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    相关资源
    最近更新 更多