【问题标题】:Segmentation Fault in Linked List C program链表 C 程序中的分段错误
【发布时间】:2017-10-05 14:04:40
【问题描述】:

我正在尝试创建一个包含 10 个节点的列表并分配值 1 到 10 并打印它们。我使用以下代码进行了尝试,但最终出现分段错误。

我对 C 中的链表很陌生。

#include<stdio.h>
typedef struct Node
{
  int data;
  struct Node *next;
}Node_Struct;

int main(void)
{
 int i =0;
 Node_Struct* Node = NULL;
 Node = (Node_Struct*)malloc(sizeof(Node_Struct));

 for (i = 1; i<=10; i++){
    Node->data = i;
    Node       = Node->next;
 }

  for (i = 1; i<=10; i++){
    printf("\n Node->data:%d",Node->data);
    Node = Node->next;
  }
 return 0;
}

【问题讨论】:

  • 您“可能”需要初始化和分配每个节点,而不仅仅是头部。
  • 您创建了一个节点,然后尝试遍历 9 个不存在的节点。
  • 使用Node= Node-&gt;next;,您可以转到下一个节点,但您忘记了列表的开始位置,通常称为head
  • 侧节点:你忘了#include &lt;stdlib.h&gt;

标签: c linked-list segmentation-fault


【解决方案1】:

正如 cmets 中的人们所指出的,您只是将内存分配给头节点。您还需要为尝试添加 int 的每个节点分配内存 for 循环。此外,您在每次迭代时都在 Node 指针上向前移动,因此您将无法在插入后遍历列表。跟踪列表的头部和尾部。执行以下操作:

维护链表的头尾:

 Node_Struct* headNode = NULL, *tailNode = NULL;
 // head node
 headNode = tailNode = (Node_Struct*)malloc(sizeof(Node_Struct));

在循环中的每次迭代时分配内存。是否要在头节点中保留某些内容是您的愿望。所以像这样改变for循环中的代码:

for (i = 1; i<=10; i++) {
   Node_Struct* newNode = (Node_Struct *)malloc(sizeof(Node_Struct));

   newNode->data = i;
   newNode->next = NULL;

   tailNode->next = newNode;
   tailNode = newNode;
}

在此之后,您可以通过将 head 值复制到其他变量中来迭代您的列表:

  Node_Struct *tmpNode = headNode;
  for (i = 1; i<=10; i++){
    printf("\n Node->data:%d",tmpNode->data);
    tmpNode = tmpNode->next;
  }

【讨论】:

    【解决方案2】:

    您没有为每个添加的节点分配内存。

    如果使用你的循环,那么做这些小改动就足够了

    Node_Struct* Node = NULL;
    Node_Struct **current = &Node;
    
    for (i = 1; i <= 10; i++ ) {
        *current = malloc(sizeof(Node_Struct));
        (*current)->data = i;
        (*current)->next = NULL;
        current = &(*current)->next;
    }
    
    current = &Node;
    for (i = 1; i <= 10; i++) {
        printf("\n Node->data:%d", ( *current )->data);
        current = &( *current )->next;
    }
    

    考虑到您应该在退出程序之前释放所有已分配给节点的内存。

    【讨论】:

      【解决方案3】:

      您只为单个节点分配了空间,但您正试图通过这样做来循环链接节点列表:

      for (i = 1; i<=10; i++){
          Node->data = i;
          Node       = Node->next;
       }
      

      当你这样做时 - Node = Node-&gt;next;Node 可能指向任何地方。您可能指向了您不应该触摸的内存。

      要记住的一件事是永远不要松开列表头部的句柄。通过维护一个副本来保持指向列表头部的指针。

      Node = malloc(sizeof(Node_Struct));
      Node_Struct *head = Node;
      

      使用malloc() 为每个节点分配空间。首先建立节点列表。一种方法是这样的:

      for (i = 1; i<=10; i++){
          Node->next = malloc(sizeof (Node_Struct));
          Node       = Node->next;
      }
      Node->next = NULL    // The last node should point to NULL
      

      之后,您可以在另一个循环中设置节点的所有data 字段,或者在执行malloc() 时将它们设置在同一个循环中。由于您已经掌握了列表中head 的句柄,因此您知道从哪里开始。像这样:

      Node = head;
      i = 0;
      while (Node) {
          Node->data = i++;
          Node = Node->next;
      }
      

      【讨论】:

      • 似乎你有压力太快给出答案。 malloc 没有初始化分配区域,还有很多细微的错误
      • @JacekCz 我在哪里说malloc 初始化分配区域?并请指出我所犯的细微错误。总是乐于学习。
      • @JacekCz 好的,虽然data 被分配了,但为了论证的目的,让我们考虑一下它没有被初始化。所以呢?未初始化变量的“错误”是什么?我没有在任何地方使用它。此外,您确实意识到我没有在我的答案中编写完整的程序,对吗?其他“微妙的错误”是什么?
      【解决方案4】:

      首先我会向您展示您的错误在哪里,然后我会重新编写代码来解决您的问题。查看我的代码并与您的代码进行比较。希望对你学习数据结构有所帮助。

      让我们看看你的错误

      #include<stdio.h>
      typedef struct Node
      {
        int data;
        struct Node *next;
      }Node_Struct;
      
      int main(void)
      {
        int i =0;
        Node_Struct* Node = NULL;
        Node = (Node_Struct*)malloc(sizeof(Node_Struct));
      
       for (i = 1; i<=10; i++){
           Node->data = i;/* till here everything fine */
           Node       = Node->next; /* now you are pointing to nowhere */
           /* in the next iteration of for loop Node->data = i will crash the application */
         /* you could have done it like below
           Node->next = (Node_Struct*)malloc(sizeof(Node_Struct));
           Node       = Node->next;
           Node->data = i;
           Node->next = NULL
           but here you lost the address of first node so all gone*/
      
       }
      
           for (i = 1; i<=10; i++){
           printf("\n Node->data:%d",Node->data);
           Node = Node->next;
        }
        return 0;
      }
      

      现在看看我下面的代码

      int main(void)
      {
          int i =0;
          Node_Struct *Node = NULL;
          Node_Struct *p = NULL;
      
          for (i = 1; i<=10; i++){
          if ( Node == NULL )
          {
               Node = (Node_Struct*)malloc(sizeof(Node_Struct));
               Node->data = i;
               Node->next = NULL;
               p = Node; /* p is pointing to the first Node of the list */
             }
             else
             {
                 p->next = (Node_Struct*)malloc(sizeof(Node_Struct));
                 p = p->next;
                 p->data = i;
                 p->next = NULL;
              }
        }
      
              p = Node; /* now p is pointing to first node of the link list */
               /* if you see above we always assign NULL to 'next' pointer so that the last node of the list    pointing to NULL */
              /* Therefore in the below while loop we are searching the list untill we reach the last node */
              while( p != NULL )
              {
                  printf("\n p->data:%d",p->data);
                  p = p->next;
               }
            return 0;
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-08-18
        • 1970-01-01
        • 1970-01-01
        • 2013-10-21
        • 2012-06-12
        • 2020-09-10
        • 1970-01-01
        相关资源
        最近更新 更多