【问题标题】:Seg fault linked list recursion in CC中的段错误链表递归
【发布时间】:2013-03-07 01:59:33
【问题描述】:

我不知道为什么会出现段错误。基本思想是使用链表递归地插入整数。

node* insert(node** head, int integer)
{
    node* temp = malloc(sizeof(node));
    node* temp1;
    node* newNode;

    if(*head == NULL)
    {
        temp->num = integer;
        temp->next = *head;
        *head = temp;
    }
    else if((*head)->num > integer)
    {
        temp = *head;
        temp1 = temp->next; //breaks the link
        temp->next = newNode;   //creates a new node
        newNode->num = integer;  //adds int
        newNode->next = temp1;   //links new node to previously broken node 
        temp1->next = *head; //next node is NULL 
        *head = temp1;  //Makes next node head again
    }

    else
        insert(&((*head)->next), integer);

    return(temp);
}

我在 GDB 中运行了这段代码,它在temp1->next = *head 处出现了错误,但我不明白为什么。我什至放了笔记来帮助自己,但我想它不起作用。有人可以告诉我为什么我会出现段错误吗?谢谢。

【问题讨论】:

  • 分段错误前head的值是多少? (head,不是*head)。我这样问,因为它可能是分段错误的根源:取消引用空指针。

标签: c recursion linked-list segmentation-fault


【解决方案1】:
temp1 = temp->next;

应该在之前

temp = *head;

如果(*head)->num > integer 和如果您想在标题中插入整数,那么您的代码会很复杂且错误。你可以这样做:

else if((*head)->num > integer)
    {
        temp->next = *head;
        temp->num = integer;
        *head = temp;
    }

temp = malloc(sizeof(node));

应该只调用到

if(*head == NULL)

进入

else if((*head)->num > integer)

所以你的最终功能可能是这样的

node* insert(node** head, int integer)
{
    node* temp;

    if(*head == NULL)
    {
        temp = malloc(sizeof(node));
        temp->num = integer;
        temp->next = *head;
        *head = temp;
    }
    else if((*head)->num > integer)
    {
        temp = malloc(sizeof(node));
        temp->next = *head;
        temp->num = integer;
        *head = temp;
    }

    else
        temp = insert(&((*head)->next), integer);

    return(temp);
}

我测试插入功能:

int main (void) {


   node *tmp, *head = NULL;
   insert(&head, 5);
   insert(&head, 7);
   insert(&head, 3);
   insert(&head, 6);
   insert(&head, 4);
   insert(&head, 2);

   for (tmp = head; tmp!=NULL; tmp = tmp->next) {
        printf("tmp->num  %d\n",tmp->num);
   }

}

它成功了!

$ ./test
tmp->num  2
tmp->num  3
tmp->num  4
tmp->num  5
tmp->num  6
tmp->num  7

【讨论】:

  • 非常感谢.. 我真的搞砸了我的 else if 语句。这是真正通过我关闭的递归。我试图在链接列表的中间插入,但我忘记了我正在遍历它并且我不必拥有所有额外的变量。
【解决方案2】:

所以当你第一次经历这个时,head 是空的,你有一个案例。

下一次遍历,head有指针,没有next节点。 head->next 为 NULL。

所以当你到达:

temp1 = temp->next; 

将其设置为 NULL。当你到达

temp1->next = *head; //next node is NULL 

哇,temp1 为空。没有 temp1->next 之类的东西,它正在寻找一个没有的结构。

编辑:
当您设置temp = *head 时,您正在丢弃刚刚分配的内存。在确定需要内存之前,您可能不应该分配内存。我的意思是,每次数字小于目标时,您都会调用 insert() 的新实例。每次通过时,您都会分配一些您实际不使用的内存。你可能想为newnode分配内存,而不是temp

而且您可能应该使用更好的命名方案。我的意思是,你第二次调用插入时,它不再是头部。 integer 可能更像intToInsertnewValuetemp1 更像savedTail。小问题,但它有助于保持直截了当,这是一个养成的好习惯。

最后,想想当你遍历列表,找到新项目所属的位置,创建一个新节点,将它的 ->next 字段设置为尾部的其余部分并返回时会发生什么。 ... 怎么办?前一个节点有一个next 值,它仍然指向它之前的值。您还需要更新该链接。

【讨论】:

    【解决方案3】:

    假设链表当前只有一个节点。

    所以 *head = 某个节点。

    *head->next = NULL。

    现在让我们看看代码:

    node* insert(node** head, int integer)
    {
        node* temp = malloc(sizeof(node));
        node* temp1;
        node* newNode;
    
        if(*head == NULL)  // condition = false
        {
            temp->num = integer;
            temp->next = *head;
            *head = temp;
        }
        else if((*head)->num > integer)  // let's assume condition = true
        {
            temp = *head;
            temp1 = temp->next; //breaks the link   // temp1 = NULL
            temp->next = newNode;   //creates a new node  // temp1 is not changed
            newNode->num = integer;  //adds int
            newNode->next = temp1;   //links new node to previously broken node 
            temp1->next = *head; //next node is NULL // NULL->next !!!
            *head = temp1;  //Makes next node head again
        }
    
        else
            insert(&((*head)->next), integer);
    
        return(temp);
    }
    

    【讨论】:

      【解决方案4】:
      *head = temp1;
      

      应该在

      之前
      temp1->next = *head;
      

      【讨论】:

        猜你喜欢
        • 2021-07-23
        • 1970-01-01
        • 2017-06-05
        • 2018-03-30
        • 2016-05-08
        • 1970-01-01
        • 2021-08-15
        • 1970-01-01
        • 2017-11-12
        相关资源
        最近更新 更多