【问题标题】:Not sure why I am getting a segmentation fault here不知道为什么我在这里遇到分段错误
【发布时间】:2019-10-30 10:30:11
【问题描述】:

我知道我可以更改代码来修复错误,但我不明白为什么会出现分段错误。感谢所有帮助,谢谢。

typedef struct nodes{
    int data;
    struct nodes *next;
} node;

int main(int argc, char * argv[]){
    node *head = NULL;
    node *tmp = NULL;
    int i;

    head = malloc(sizeof(node));
    tmp = head;
    for(i = 0; i < 10; i++){
        tmp->data = i;
        tmp->next = malloc(sizeof(node));
        tmp = tmp->next;
    }
    tmp = NULL;
    for(tmp=head; tmp->next != NULL; tmp = tmp->next){
        printf("%d\n", tmp->data);
    }

}

这是输出:

0
1
2
3
4
5
6
7
8
9
0
Segmentation fault: 11

【问题讨论】:

    标签: c list linked-list segmentation-fault nodes


    【解决方案1】:

    最后一个节点的next指针未设置为null。因此,第二个for-loop 中的条件tmp-&gt;next != NULL 将永远不会满足。实际上,您可以看到在最后一个数字 (9) 之后,在 seg 故障发生之前打印了一些垃圾数字 (0)。

    当你这样做时:

    tmp-&gt;next = malloc(sizeof(node));

    您还应该添加如下内容:

    tmp-&gt;next-&gt;next = NULL;

    通过这种方式,您可以“安全地”初始化每个节点,并将 next 指针设置为 NULL。除最后一个节点外,所有节点都将在下一次迭代中获得正确的值。

    EDIT 正如@Someprogrammerdude 在评论中指出的那样,即使您按照上面的建议进行操作,最后也会得到一个额外的节点。 要解决这个问题,您可以按如下方式更改创建循环:

    for(i = 0; i < 10; i++){
        tmp->data = i;
        if (i < 9) {
            tmp->next = malloc(sizeof(node));
        } else {
            tmp->next = NULL;
        }
        tmp = tmp->next;
    }
    

    【讨论】:

    • 实际上,整个循环及其分配是错误的。如果 OP 试图创建一个包含十个节点的列表,那么“最后一个”(第十个)节点将有一个指向第十一个节点的指针,而没有初始化 datanext 成员。
    • @Someprogrammerdude:好点,你是对的,即使我提出的解决方案,他最终也会出现“垃圾”节点。我将编辑答案以指出这一点。
    • 有没有比每次迭代都检查 'i
    • for-loop 之后的一个简单的tmp-&gt;next= NULL; 就足够了。
    【解决方案2】:

    通过向后构建列表,您将获得更简洁的代码。换句话说,首先将最后一个节点添加到列表中,然后在列表的开头插入其他节点。代码如下所示:

    node *head = NULL;
    for (int i = 9; i >= 0; i--)
    {
        node *tmp = malloc(sizeof(node));
        tmp->data = i;
        tmp->next = head;
        head = tmp;
    }
    

    请注意,由于head 最初是NULL,因此列表中的最后一个节点的next 指针将设置为NULL。这就是您的代码中缺少的内容。

    【讨论】: