【问题标题】:C segmentation fault when using pointer to structure in a linked list在链表中使用指向结构的指针时出现 C 分段错误
【发布时间】:2016-02-12 15:42:46
【问题描述】:

我用 C 语言编写了一个非常基本的链表,仅支持两个操作 - 将节点插入到列表顶部并遍历列表以打印每个节点的值。我面临的问题是执行时出现分段错误。这是我的代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct linkedList
{
    int data;
    struct linkedList *next;
};
struct linkedList* createNode(int value)
{
    struct linkedList *node;
    node = malloc(sizeof(struct linkedList));
    node->next = malloc(sizeof(struct linkedList));
    node->next = NULL;
    node = NULL;
    return node;
}
//insert a node at the top of the linked list
struct linkedList* insertTop(struct linkedList* top,struct linkedList* node)
{
    if(top == NULL)//the element we insert is the 1st element for the linked list
    {
        node->next = NULL;
        //the first element points to NULL since it has no successors
    }
    else//there is already an element in the list
    {
        node->next = top;
    }
    return node;
}
void iterate(struct linkedList* top)
{
    while(top->next != NULL)
    {
        printf("Data = %d\n", top->data);
        top = top->next;
    }
}
int main()
{
    struct linkedList *a,*b,*c,*root;
    a = createNode(2);
    b = createNode(10);
    c = createNode(23);
    root = insertTop(NULL,a);//these 3 lines provoke a segmentation fault
    root = insertTop(root,b);
    root = insertTop(root,c);
    iterate(root);//the result I expect here is 23,10,2 
    return 0;
}

我知道这个问题已经在 stackoverflow 上被问过很多次,但我仍然无法弄清楚为什么我的代码不能按预期工作。 您能否向我解释问题出在哪里以及如何解决?谢谢

【问题讨论】:

  • createNode() 中为什么要在返回之前输入node = NULL。你正在失去你刚刚malloced的记忆。
  • 你分配 node->next,然后将其设置为 NULL 将其丢弃。然后将节点指针设为 NULL 并返回...
  • 是的..返回NULL...
  • createNode()createMemoryLeak()...
  • 它也在创建下一个节点并将其无效。这很有趣。

标签: c pointers struct linked-list


【解决方案1】:

有两个主要问题。先createNode

您为struct linkedList 分配空间并将其分配给node,这很好。但是你对node-&gt;next 做同样的事情。所以你实际上是在创建两个节点,但是你将 node-&gt;next 设置为 NULL ,失去对你分配的第二位内存的引用,从而造成内存泄漏。当您对node 执行相同操作时,也会发生同样的情况。最终结果是您始终为新节点返回 NULL。此外,您不会将 value 分配给任何东西。

只做第一次分配,将value赋值给data,并将next初始化为NULL:

struct linkedList* createNode(int value)
{
    struct linkedList *node;
    node = malloc(sizeof(struct linkedList));
    node->data = value;
    node->next = NULL;
    return node;
}

下一期在iterate

while(top->next != NULL)

当当前节点是最后一个节点时,这会导致迭代停止,因此您不会打印最后一个节点。此外,由于 createNode 最初的实现方式,您的 root 指针为 NULL,因此您最终取消引用 NULL 指针,这会导致核心转储。

您想测试 top 是否为 NULL:

while(top != NULL)

第三个问题是清理。您需要在程序退出之前为free 分配的内存定义一个函数。你可以这样做:

void cleanup(struct linkedList *top)
{
    struct linkedList *temp;

    while (top != NULL) {
        temp = top;
        top = top->next;
        free(temp);
     }
}

【讨论】:

  • 感谢您的完整回答!在 [cleanup] 函数中,您已将 temp 声明为 struct linkedList 类型的变量,在我看来它应该是指向 linkedList 类型的指针。 temp 是否必须是指向linkedList 的指针,如果是,出于什么原因它应该是指针?当使用 temp 作为类型为 linkedList 的简单变量时,编译器会在 node 和 top 之间显示“不兼容的类型”。
  • @traviata 这是一个错字。它应该是struct linkedList *。我已经编辑了答案。
【解决方案2】:

这个:

node = NULL;

createNode() 函数中看起来不太好。事实上,整个功能看起来并不那么好。应该是这样的:

struct linkedList* createNode(int value)
{
    struct linkedList *node = malloc(sizeof *node);
    node->next = NULL;
    node->data = value;
    return node;
}

真的不应该分配多个节点,这很不理智。

【讨论】:

    【解决方案3】:

    如果您想创建一个节点,您只需为一个节点分配内存。像这样调整你的代码:

    struct linkedList* createNode(int value)
    {
        struct linkedList *node = malloc(sizeof(struct linkedList));
        node->next = NULL;
        node->data = value;
        return node;
    }
    

    除此之外,您还必须在函数iterate 中更改while 循环的终止条件:

    void iterate( struct linkedList *top )
    {
        while( top != NULL) // if to is not NULL you can print its data
            // ^^^ 
        {
            printf("Data = %d\n", top->data);
            top = top->next;
        } 
    }
    

    你可以简化你的函数insertTop:

    struct linkedList* insertTop(struct linkedList* top,struct linkedList* node)
    {
        if( node == NULL ) // test if node is not NULL
            return top;
        node->next = top;  // successor of new node is top (top possibly is NULL)
        return node;
    }
    

    别忘了free你的名单在main末尾:

    int main()
    {
        struct linkedList *root = NULL;
        root = insertTop( root, createNode(2) );
        root = insertTop( root, createNode(10) );
        root = insertTop( root, createNode(23) );
    
        iterate(root);
    
        while ( root != NULL )
        {
            struct linkedList *temp = root;
            root = root->next; 
            free( temp );
        }
        return 0; 
    }
    

    除此之外,您还可以将createNodeinsertTop 组合成一个函数createTop

    struct linkedList* createTop( struct linkedList* top, int value )
    {
        struct linkedList *node = malloc(sizeof(struct linkedList));
        node->next = top;
        node->data = value;
        return node;
    }
    

    【讨论】:

      【解决方案4】:

      你有很多问题..

      在函数createNode() 中,您将内存分配给node,然后通过执行node = NULL 将其丢弃。

      松开这些语句,因为它们会造成内存泄漏。

      struct linkedList* createNode(int value)
      {
          struct linkedList *node;
          node = malloc(sizeof(struct linkedList));
          node->data = value;
          node->next = NULL;
          return node;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-20
        • 1970-01-01
        • 2023-03-17
        • 1970-01-01
        • 2015-09-10
        • 1970-01-01
        • 1970-01-01
        • 2016-02-23
        相关资源
        最近更新 更多