重新排列双向链接列表时偶尔出现段错误

时间:2019-05-05 00:36:58

标签: c segmentation-fault doubly-linked-list

很抱歉,对于某些人来说这似乎微不足道,但在过去的一天中,我无法终生弄清楚为什么发生这种段错误。我有一个双向链接列表数组,它们保持一定顺序。每次访问或更新列表中的节点时,它都会移到列表的开头,并且在数组中的每个链接列表中都会发生。我将提供有关如何初始化链接列表数组以及如何排列顺序的代码。任何帮助表示赞赏。如果有帮助,则双链表的数组是为了模拟缓存。我只是希望它的内容显而易见,因为我对malloc和C有点陌生。第一次使用此站点,所以请让我知道我是否未遵循惯例或帖子做错了什么

我已经尝试打印出链表数组的结构,而且看起来在结构上总是很合理的。仅当我重新排列节点时才会发生段错误,特别是当我尝试访问Node-> prev-> next时。不仅如此,当我专门更新尾节点时也会发生

void maintainLRU(cacheBlock* ptr, int index)//rearranges a list with node passed in to be head
{
    if(ptr->next == NULL)//Tail
    {
        ptr->next = cache[index].head;
        cache[index].head = ptr;
        cache[index].tail = ptr->prev;
        ptr->prev->next = NULL;
        ptr->prev = NULL;
    }
    else
    {
        ptr->prev->next = ptr->next;
        ptr->next = cache[index].head;
        cache[index].head = ptr;
        ptr->prev->next = NULL;
        ptr->prev = NULL;
    }
}

//following code exists within main and is how i initialize the'cache'
numLines = cacheSize/(blockSize*assocType); //determines number of linked lists in my array. 
cache = malloc(sizeof(cacheLine)*numLines);
for(int i = 0; i < numLines; i++)
{
        cacheBlock* temp = malloc(sizeof(cacheBlock));
        temp->valid = 0; //whether the node holds data yet or not
        cache[i].head = temp;
        for(int j = 1; j < assocType; j++)//assoctype is just how many nodes in the list
        {
            temp->next = malloc(sizeof(cacheBlock));
            temp->next->prev = temp;
            temp->next->valid = 0;
            temp = temp->next;
        }
        cache[i].tail = temp;
}//cacheblock is just a node with next, prev, and a valid bit
//cacheLine is just a struct with a pointer to a headnode
//the maintain order function is explicitly called only if the node updated or accessed is not the head.```

1 个答案:

答案 0 :(得分:1)

情况1:ptr位于列表的末尾  您正确地将自己移开,将自己放在列表的开头,但不要使列表的“旧”标题成为指向您的开头;因此您的列表已损坏。

情况2:ptr不在列表末尾  您将上一个指向下一个,但是不要将下一个指向上一个,因此您的列表已损坏。

所有情况:您应该提供足够的程序,以便其他人可以对其进行编译和尝试。在某种程度上,这将使您对工作进行足够的分析以发现明显的错误。精妙的是这个论坛的目的。

3年前,严格优化链接列表操作非常重要;在那个时候,编译器的书呆子提高了他们的游戏水平,以至于您应该能够将maintainLRU编写为:

void maintainLRU(cacheBlock* ptr, int index) {
    list_remove(&cache[index], ptr);
    list_insert_before(&cache[index], cache[index].head, ptr);
}

所以您不会成为简单错误的受害者。