添加和删​​除双链表

时间:2015-01-11 20:00:19

标签: c doubly-linked-list

我有这个结构

typedef struct node
{
    struct node *prev;
    void        *data;
    struct node *next;
}NODE;

typedef struct head
{
    unsigned int length;
    struct node  *first;
    struct node *last;
}HEAD;


STATUS addNode(HEAD *head, NODE *newNode, int loc)
{
int i;
STATUS ret = SUCCESS;

NODE *curPtr;

if(head && newNode && loc && (loc <= (head->length)+1))
{
    if(loc == 1)
    {
        newNode->prev = NULL;
        newNode->next = head->first;

        if(head->first)
            head->first = newNode;
    }
    else
    {
        curPtr = head->first;

        for(i=1; i<(loc-1); i++){
            curPtr = curPtr->next;
        }

        newNode->prev = curPtr;
        newNode->next = curPtr->next;

        if(curPtr->next){
            curPtr->next->prev = newNode;
        }
        curPtr->next = newNode;

    }

    head->length++;
}
else
    ret = FAILURE;

return ret;
}



STATUS removeNode(HEAD *head,NODE *nodeToRemove)
{
    STATUS ret = SUCCESS;

    NODE *curPtr;

    if(head && head->first)
    {
        curPtr = nodeToRemove->prev;
        curPtr->next = nodeToRemove->next;
        if(!(curPtr->next)){
            curPtr->next = head->first;
        }
        head->length--;
    }
    else
        ret = FAILURE;

    return ret;
}

我知道我没有从列表中删除免费(节点),此调用是在其他地方进行的

我的问题是,有时在添加节点的newNode->next = curPtr->next;行上它会出现分段错误

你可以告诉我它可能发生的原因吗?

2 个答案:

答案 0 :(得分:1)

好的,让我们从我的第一条评论开始:当您使用addNode调用loc == 1函数时会发生什么:初始化新节点,因此它的next指针指向列表的旧头部,prev指针指向NULL。这一切都很好,但随后你的问题开始了。如果列表为空,则只将新节点添加到列表。您也不会更改以前的头节点prev指针。

这意味着如果列表为空(即head->firstNULL时),则不会添加节点,列表将继续为空。如果列表不为空,那么你有一个双链表,你只能走一条路(从(新的)第一个节点到(新的)第二个节点,你不能走相反的方向,因为你没有设置这样的链接。


现在我的第二和第三条评论:loc != 1时的循环。首先,如果loc == 0,它将不会运行,这意味着它将添加到头部(这是您在loc == 1时尝试执行的操作)。如果列表为空,这将无效,因为curPtr将为NULL,当您取消引用该指针时,您将拥有undefined behavior

其次,假设您已设法将一些节点添加到列表中,并且您传递的值大于节点数加上列表中的一个loc(即如果您有一个节点,那么您传递一个大于2的值,或者你有五个节点并传递一个大于6的值),然后循环将迭代一次到多次,让curPtr为{{1} }}。您不会在任何地方检查,这意味着您迟早(在循环中或之后)尝试取消引用导致undefined behaviorNULL指针。


Undefined behavior是崩溃的最常见原因,例如您拥有的崩溃。下次发生崩溃时,首先应该使用调试器并在其中运行程序。调试器将在崩溃位置停止,让您检查函数调用堆栈,以及向上调用堆栈。您还可以检查调用堆栈每个级别的变量值(如果调试器具有该级别的信息)。您还应该尝试在调试器中逐行遍历代码,针对不同的场景,看看您打算实际发生的事情如果您仍然难倒,那么您可以来SO并发布一个关于它的问题。在编译器旁边,调试器是程序员的最佳工具。哦,广告说编译器,总是在尽可能多的警告启用的情况下构建,因为编译器非常擅长检测可疑的东西并且可能导致UB(未定义的行为)。

答案 1 :(得分:0)

可能curptr->next未分配给任何不一定使其指向NULL的内容,因此您可能会在运行时遇到分段错误。确保在构建列表时,NODE中的所有指针在对它们进行任何赋值/操作之前都会初始化为NULL。

请参阅:C: Why do unassigned pointers point to unpredictable memory and NOT point to NULL?

并且:Why am I getting a segmentation fault?