【问题标题】:Segmentation Fault - Linked List分段错误 - 链表
【发布时间】:2013-07-09 21:32:03
【问题描述】:

我正在学习如何在 C 中构建链表。我的程序可以编译,但由于某种原因我无法弄清楚,我遇到了分段错误。我一直在试图找出问题所在,但我没有任何运气。这是错误代码:

int len()
{
    struct list * current = head;
    int length = 0; 

    while (current != NULL)
    {
        length++;
        current = current -> next; //move to next node
    }
    return length; 
}


struct list * search ( int key)
{
    struct list * current = head;

    while (current != NULL && current->data != key)
        current = current -> next;

    if (current != NULL && current -> data == key)
        return current;
    return NULL;
}



/* Insert a new data element with key d into the end of the list. */
void insert(int d )  //  at the end
{
    struct list * current = head; 
    struct list * new;
    while (current -> next != NULL)
        current = current -> next;
    new = (struct list *)malloc(sizeof(struct list));
    new -> data = d; 
    current -> next = new;
    new -> next = NULL;     
}


void insertAfter(int d, int where )  //  insert at the middle
{
    struct list * marker = head;
    struct list * new;

    while(marker -> data != where)
        marker = marker -> next;
    new = (struct list*)malloc(sizeof(struct list));

    new -> next = marker -> next; 
    marker -> next = new;
    new -> data = d; 
}


/* Remove the node with value d from the list */
/* assume no duplicated keys in the list */
/* If the list is empty, call prtError() to display an error message and return -1. */

void delete(int d)
{
    struct list * current1 = head; 
    struct list * current2;

    if (len() == 0)
    { //prtError("empty");
        exit(0);
    }
    if (head -> data == d)
    { 
        head = head -> next;
    }

    //Check if last node contains element
    while (current1->next->next != NULL)
        current1 = current1->next;

    if(current1->next->data == d)
            current1->next == NULL; 


    current1 = head; //move current1 back to front */

    while(current1 -> next -> data != d)
        current1 = current1 -> next; 

    current2 = current1 -> next;
    current1 -> next = current2 -> next; 

}

我在以下行的删除方法中遇到分段错误

while(current1 -> next -> data != d)

为什么会这样?

【问题讨论】:

  • 您在哪个函数中遇到分段错误?
  • 如果在调试器中运行,调试器在哪里说发生了分段错误?
  • 我不认为 new 在 C 中是保留的,但您可能不应该将它用作变量名。你的 delete 函数看起来很可能是候选函数,你有 if (head -> data == d) 没有检查 NULLcurrent1->next->next 可能也不好,insertcurrent -> next 没有检查 NULL
  • 插入方法出现分段错误-whole(current -> next != NULL)

标签: c list linked-list segmentation-fault


【解决方案1】:

你有几个问题,insert:

while (current -> next != NULL)

您没有检查current 是否为NULLdelete也有类似问题:

if (head -> data == d)

您需要在此处查看head 并且:

while (current1->next->next != NULL)

也是一个问题。

【讨论】:

  • “current -> next = new;”处还有一个问题在插入方法中。这条线有什么问题?这是我第一次尝试 C 中的链表,我还在学习!
  • @Sophie 这行while(current->next != NULL) current = current->next; 将确保currentNULL
  • 我在以下行的删除方法中遇到分段错误:while(current1 -> next -> data != d)
【解决方案2】:

insert after 有一个错误,你将超出列表的末尾找不到元素。

【讨论】:

    【解决方案3】:

    您发布的代码存在很多问题,但是您在 cmets 中提到您担心insert()。它崩溃的原因是,如果在调用 insert()head 为 NULL,您将取消引用 NULL 指针。

    head 为 NULL 时,您将需要一个特殊情况插入:

    if (head) {
        while (current -> next != NULL)
            current = current -> next;
    }
    new = (struct list *)malloc(sizeof(struct list));
    new -> data = d;
    if (current) {
        current -> next = new;
    } else {
        head = new;
    }
    new -> next = NULL;
    

    您应该检查其他功能中是否存在类似问题。使用您的 search() 函数作为避免在循环中取消引用 NULL 指针的示例。

    【讨论】:

      【解决方案4】:

      insert

      while(current->next != NULL) current = current->next;
      

      这将保证current == NULL

      current->next = new;
      

      每次都会崩溃。

      【讨论】:

        【解决方案5】:

        也许在insertAfter:

        while(marker -> data != where)
            marker = marker -> next;
        

        如果没有找到带有data == where 的节点,marker 将是一个NULL 指针。
        NULL 指针稍后在您的代码中被取消引用:

        new = marker -> next;
        

        它会产生段错误。检查marker->next != NULL 是否应该避免这种情况:

        while(marker->next != NULL && marker -> data != where)
            marker = marker -> next;
        

        但是您应该尝试使用调试符号(-g 选项)编译您的程序,并在 GDB 等调试器中逐行运行它。

        【讨论】:

          猜你喜欢
          • 2018-02-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-06
          相关资源
          最近更新 更多