是什么导致双向链表中追加节点函数的分段错误?

问题描述

我的双向链表实现如下,每个节点保存一个包含四个值的数组

#define EMPTYNODE 0

struct node {
short data[4]; // pay attention
struct node* next;
struct node* prev;
};

typedef struct node nodeQ_t;

typedef enum{
   LIST_FALSE = 0,LIST_TRUE = 1,} status_t;

nodeQ_t* createNode(short values[4]){

    nodeQ_t* node = (nodeQ_t*)malloc(sizeof(node));
    for(int i=0; i < 4; i++){
       node->data[i] = values[i];
     }

   node->next = EMPTYNODE;
   node->prev = EMPTYNODE;
   return node;
}

现在我试图以一种方式编写 append 函数,我提供它头和在 createNode 函数中创建的节点,以便它将它附加到列表中......但它会创建一个分段错误......>

status_t appendNode(nodeQ_t* head,nodeQ_t* newNode){
if(head == EMPTYNODE || newNode == EMPTYNODE){
    return LIST_FALSE;
};

nodeQ_t* currentNode = head;

while(currentNode != EMPTYNODE){
    if(currentNode->next == EMPTYNODE){ //it means that current node is tail
        currentNode->next = newNode;  //segmenttion fault arises at exactly this line 
        newNode->prev = currentNode;
    }
    currentNode = currentNode->next;
}
return LIST_TRUE;
}

请告诉我这是什么原因... 供您参考,我的主要功能

int main(){
  short array[4] = {1,2,3,4};

  nodeQ_t* head  = createNode(array);

  printList(head);


  short array2[4] = {5,6,7,8};

  nodeQ_t* newNode = createNode(array2);

  appendNode(head,newNode);


  printList(head);



  return 0;

}

如果您需要任何进一步的信息或解释,请告诉我

解决方法

正如评论中提到的,一旦到达终点,您需要break退出循环:

while(currentNode != EMPTYNODE) {
    if (currentNode->next == EMPTYNODE) {
        currentNode->next = newNode;
        newNode->prev = currentNode;
        // need a break here
    }
    currentNode = currentNode->next;
    // When at the end of the list the 1st time through,// currentNode is the newly created node because you have
    //     currentNode->next = newNode
    // then
    //     currentNode = currentNode->next
    // On the next iteration,the new node next ends up getting pointed to itself 
    // since on that iteration newNode and currentNode are the same.
    // and you end up with an infinite loop.
}

另一种选择是在 currentNode->next 上循环:

while (currentNode->next) {
    currentNode = currentNode->next;
}
currentNode->next = newNode;
newNode->prev = currentNode;

我应该注意到这是有效的,因为您之前确保 currentNode 不是 NULL

另外,你这里的分配是错误的:

nodeQ_t* node = (nodeQ_t*)malloc(sizeof(node));

因为 node 是一个指针,而 sizeof(node) 是一个指针的大小,而不是 struct node 的大小。应该

nodeQ_t* node = (nodeQ_t*)malloc(sizeof(*node));
,

你最终陷入无限循环:

while(currentNode != EMPTYNODE){
    if(currentNode->next == EMPTYNODE){ //it means that current node is tail
        currentNode->next = newNode;  //segmenttion fault arises at exactly this line 
        newNode->prev = currentNode;
    }

currentNode 将始终与 EMPTYNODE 不同。 添加新元素后添加中断或返回:

while(currentNode != EMPTYNODE){
    if(currentNode->next == EMPTYNODE){ //it means that current node is tail
        currentNode->next = newNode;  //segmenttion fault arises at exactly this line 
        newNode->prev = currentNode;
        return LIST_TRUE;
    }