【问题标题】:Getting segmentation fault when trying to print linked list data reversely using recursion尝试使用递归反向打印链表数据时出现分段错误
【发布时间】:2019-09-13 10:13:33
【问题描述】:

我已经创建了节点链表。并想使用 recursion 技术反向打印每个节点的数据。我得到了工作代码和段错误代码。我正在尝试了解分段错误代码中的实际问题。

实际上我尝试使用 GDB 进行调试,但我不知道如何解决这个问题。任何线索都将有助于清楚地理解递归。

#include <stdio.h>
#include <stdlib.h>

typedef struct node {
        char c;
        struct node *next;
} node_t;

node_t *head = NULL;

void insert_list(node_t *node)
{
    static node_t *temp = NULL;
    if (!head) {
        head = node;
        //temp = node;
    }
    else {
        temp->next = node;
    }
    temp = node;

}

void create_list(char c)
{
    node_t *temp = NULL;
    temp = malloc(sizeof(node_t));
    if (temp) {
        temp->c = c;
        temp->next = NULL;
        insert_list(temp);
    }
    else
        return;
}

void print_list_reversely(node_t *temp)
{
    if (!temp)
        return;
    //print_list_reversely(temp->next); /* Working piece */
    temp = temp->next; /* This and next line together*/
    print_list_reversely(temp); /* Causing SEGFAULT */
    printf("data is %c\n", temp->c);
    return;
}

int main()
{
    create_list('a');   
    create_list('b');   
    create_list('c');
    print_list_reversely(head);
    return 0;
}

经过一些 GDB 调试得到以下信息:

A) print_list_reversely(temp->next);

Breakpoint 4, print_list_reversely (temp=0x0) at create.c:40
40      if (!temp)
(gdb) p temp
$5 = (node_t *) 0x0
(gdb) n
41          return;
(gdb) n
47  }
(gdb) n
print_list_reversely (temp=0x602050) at create.c:45
45      printf("data is %c\n", temp->c);

=======

B) temp = temp->next; print_list_reversely(temp);

Breakpoint 4, print_list_reversely (temp=0x0) at create.c:40
40      if (!temp)
(gdb) p temp
$3 = (node_t *) 0x0
(gdb) n
41          return;
(gdb) n
47  }
(gdb) 
print_list_reversely (temp=0x0) at create.c:45
45      printf("data is %c\n", temp->c);

【问题讨论】:

标签: c recursion linked-list segmentation-fault


【解决方案1】:

假设你在最后一个节点。

//temp = temp->next; /* This and next line together*/
//print_list_reversely(temp); /* Causing SEGFAULT */
printf("data is %c\n", temp->c);

您将tmp 分配给NULL 并尝试打印它导致NULL 指针取消引用。


考虑你有如下列表

1->2->NULL

你的递归调用是

print_list_reversely(1)
           tmp = [2]
                 --->      print_list_reversely(2)
                           tmp = [NULL]
                                          --->      print_list_reversely(NULL)
                                                    return;
                           print(null->c) //Seg fault

【讨论】:

    【解决方案2】:

    递归中传入的最后一个指针temp是NULL,所以访问NULL必然会导致段错误

    Program received signal SIGSEGV, Segmentation fault.
    0x00000000004005c1 in print_list_reversely (temp=0x0) at linked_list.c:40
    40      printf("data is %c\n", temp->c);
    (gdb) bt
    #0  0x00000000004005c1 in print_list_reversely (temp=0x0) at linked_list.c:40
    #1  0x00000000004005bd in print_list_reversely (temp=0x601050) at linked_list.c:39
    #2  0x00000000004005bd in print_list_reversely (temp=0x601030) at linked_list.c:39
    

    【讨论】:

      【解决方案3】:

      您的方法 print_list_reversely() 从第一个元素到最后一个元素被递归调用,这就是预期的行为。

      看看你是如何定义你的列表的,最后一个元素将是NULL

      如果你取消注释你的两个错误行(编辑:你现在取消注释它们),当 temp = temp-&gt;next; 在最后一个元素上执行时,你有 null。你用printf("data is %c\n", temp-&gt;c);取消引用这个指针

      因此,此代码不正确且存在段错误。

      在回调函数(或取消引用它!)之前,你必须检查你的指针不为空。

      【讨论】:

      • 但是每次移动 temp 之后,都会调用 print_list_reversely(temp),它在开始时本身 rt 进行 NULL 检查。
      • @renga_in_stack 是的,但是您是否在分配temp = temp-&gt;next 之后 执行相同的空指针检查?
      • @Someprogrammerdude :我试图理解以下代码之间的逻辑差异: print_list_reversely(temp->next); Vs 温度 = temp-> 下一个; print_list_reversely(temp);
      • @renga_in_stack 问题不在于递归调用,问题在于之后的printf 调用,您使用temp-&gt;c 取消引用空指针。好吧,这就是您拥有的 一个 空指针取消引用。
      • @renga_in_stack 看看生成的代码?使用 Godbolts compiler explorer 等工具可以很容易地并排看到这些差异。
      猜你喜欢
      • 2017-11-12
      • 1970-01-01
      • 1970-01-01
      • 2013-01-01
      • 1970-01-01
      • 2021-11-30
      • 2015-05-18
      • 2013-06-02
      • 1970-01-01
      相关资源
      最近更新 更多