尝试将节点插入链接列表时出现分段错误

时间:2015-07-07 15:12:36

标签: c list insert segmentation-fault

我几天前通过“C语言编程”一书开始学习C编程,而且我之前对java有所了解。在java中将节点插入到链表中非常容易,但我想如果我能在C中做同样的事情。 所以,我想出了这个程序,

#include "node.h"

void insertEntry(struct node* root, struct node* after)
{
    struct node* first = root;
    while(first != (struct node*) 0)
    {
        if(first->value == after->value)
        {
            struct node ins;
            ins.value = 3456;
            ins.next = first->next;
            first->next = &ins;
        }
        first = first->next;
    }
}

int main(void)
{
    struct node n1, n2, n3;
    struct node* list_pointer = &n1;

    n1.value = 100;
    n1.next = &n2;

    n2.value = 200;
    n2.next = &n3;

    n3.value = 300;
    n3.next = (struct node*) 0;

    void insertEntry(struct node* root, struct node* after);

    while (list_pointer != (struct node*) 0)
    {
        printf("%i\n", list_pointer->value);
        list_pointer = list_pointer->next;
    }
    printf("\n");

    list_pointer = &n1;

    insertEntry(list_pointer, &n2);

    while (list_pointer != (struct node*) 0)
    {
        printf("%i\n", list_pointer->value);
        list_pointer = list_pointer->next;
    }

    return 0;
}

node.h

#include <stdio.h>

struct node
{
    int value;
    struct node* next;
};

基本上,这个程序将指针指向链表的第一个元素,指向要插入它的元素的指针,并在该节点之后插入一个新节点。

但是当我运行它时,我的程序崩溃了,我无法找到发生此错误的位置或原因。 我查看了java中的代码并尝试在C中实现相同的内容。

谢谢。

3 个答案:

答案 0 :(得分:4)

这是你的问题:

    {
        struct node ins;  // You create an object in the stack
        ins.value = 3456;
        ins.next = first->next;
        first->next = &ins;   // You reference your object
    }  // Your object is popped out of the stack and ceases to exist
    // Any access to first->next past this block may cause segfault

为了避免这种情况,你可以用ins创建malloc(),但要注意:这不是java,你必须自己跟踪你在堆中分配的所有对象。

答案 1 :(得分:3)

主要问题是你插入了一个在堆栈上分配的节点 - 一旦剩下这个功能它就会无效。要分配新内存,您需要malloc()(完成后不要忘记free(),没有垃圾回收)。

一些附注:

  • 当用作指向任何特定指针类型的指针时,强制转换为0毫无意义... 0为0.

  • 您不需要插入根节点,那么为什么要在第一时间传递它?

  • 声明一个函数内部的原型(在这种情况下:main)没有多大意义......它可以不用,因为你要调用的函数已经在同一个文件中定义了。 / p>

  • #include标题,需要它们! node.h不需要stdio,主程序可以。

大致可以使用的程序版本:

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

struct node
{
    int value;
    struct node *next;
};

struct node *insertEntry(struct node* after, int val)
{
    assert(after); /* not NULL */

    struct node *new = malloc(sizeof(struct node));
    new->value = val;
    new->next = after->next;
    after->next = new;
    return new;
}

void freeNodeList(struct node* root)
{
    struct node *current, *last;

    current = root;

    while (current)
    {
        last = current;
        current = current->next;
        free(last);
    }
}

int main(void)
{
    struct node *n1, *n2, *n3;
    struct node *ptr;

    n1 = malloc(sizeof(struct node));
    n2 = malloc(sizeof(struct node));
    n3 = malloc(sizeof(struct node));

    n1->value = 100;
    n1->next = n2;

    n2->value = 200;
    n2->next = n3;

    n3->value = 300;
    n3->next = 0;

    insertEntry(n2, 250);

    ptr = n1;
    while (ptr)
    {
        printf("%d\n", ptr->value);
        ptr = ptr->next;
    }

    freeNodeList(n1);
    return 0;
}

答案 2 :(得分:0)

您应该阅读gdb以及如何使用它。

gcc -Wall -O0 -g x.c -o x 

x是您使用debuging信息进行编译而无需优化的程序。

然后通过gdb运行程序以查找故障的位置/发生。 即

gdb x