C语言中main方法中链表遍历的分段错误

C语言中main方法中链表遍历的分段错误,c,linked-list,C,Linked List,获取段zsh:从main方法遍历链表时出现的段错误(核心转储)。但在调用printList方法时效果良好。我想得到一些直观的解释,以及如何使它从主方法工作 #include <stdio.h> #include <string.h> struct Node{ int data; struct Node *next; }; void printList(struct Node *head){ struct Node *cursor= head; w

获取段zsh:从main方法遍历链表时出现的段错误(核心转储)。但在调用printList方法时效果良好。我想得到一些直观的解释,以及如何使它从主方法工作

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

void printList(struct Node *head){
   struct Node *cursor= head;
   while(cursor !=NULL){
     struct Node currentNode = *cursor;
     printf("%d -->",currentNode.data);    
     cursor=currentNode.next;
   }
}

int main(){
   struct Node *head;     
   struct Node node1;
   node1.data=11;
   struct Node node2;
   node2.data=12;
   struct Node node3;
   node3.data=13;
   struct Node node4;
   node4.data=14;   

  // printf("Node 1 %d ",node1.data);
  // printf("Node 2 %d ",node2.data);
  // printf("Node 3 %d ",node3.data);

   head = &node1;
   node1.next=&node2;
   node2.next=&node3;
   node3.next=&node4;
  // printf("Node 1 %d ",node1.data);
  // printf("Node 2 %d ",node2.data);
  // printf("Node 3 %d ",node3.data);   
  // printList(head); 
struct Node *cursor= head;
   while(cursor !=NULL){
       struct Node currentNode = *cursor;
       printf("%d -->",currentNode.data);
       cursor=currentNode.next;
    }


   return 0;
}
#包括
#包括
结构节点{
int数据;
结构节点*下一步;
};
无效打印列表(结构节点*头){
结构节点*光标=头部;
while(光标!=NULL){
结构节点currentNode=*游标;
printf(“%d-->”,currentNode.data);
cursor=currentNode.next;
}
}
int main(){
结构节点*头部;
结构节点node1;
节点1.数据=11;
结构节点node2;
节点2.数据=12;
结构节点node3;
节点3.数据=13;
结构节点node4;
节点4.数据=14;
//printf(“节点1%d”,节点1.data);
//printf(“节点2%d”,节点2.data);
//printf(“节点3%d”,节点3.数据);
头=&node1;
node1.next=&node2;
node2.next=&node3;
node3.next=&node4;
//printf(“节点1%d”,节点1.data);
//printf(“节点2%d”,节点2.data);
//printf(“节点3%d”,节点3.数据);
//印刷品清单(标题);
结构节点*光标=头部;
while(光标!=NULL){
结构节点currentNode=*游标;
printf(“%d-->”,currentNode.data);
cursor=currentNode.next;
}
返回0;
}

Make
node4.next=NULL
结束遍历。这就是你面临问题的原因

否则请检查
光标的条件=NULL
将永远不会终止。因为它包含一些垃圾值。(如果不初始化)

  • 同样对于100个节点,您会将整个创建过程写100次吗
您应该创建一个方法来将节点添加到列表的头部。那将是理想的

还可以阅读一些关于动态内存分配的内容。为了推动你,我提供了一些想法。阅读它,检查手册

例如,如果要动态分配节点。您可以这样做:-

struct node *tempNode;
tempNode = malloc(sizeof(struct node));
if(tempNode == NULL){
    fprintf(stderr,"%s","Error in malloc");
    exit(1);
}
..
...
无论您使用
malloc
分配什么,请在逻辑末尾释放它

大概

free(tempNode);
tempNode=NULL;

回答您的评论:-不要依赖未定义的行为。取消引用垃圾值会调用未定义的行为。您必须避免它,以使您的程序行为稳定


小事一桩

 struct Node currentNode = *cursor;
 printf("%d -->",currentNode.data);    
可以在一行中轻松完成

 printf("%d -->",cursor->data); //Also (*cursor).data

使
node4.next=NULL
结束遍历。这就是你面临问题的原因

否则请检查
光标的条件=NULL
将永远不会终止。因为它包含一些垃圾值。(如果不初始化)

  • 同样对于100个节点,您会将整个创建过程写100次吗
您应该创建一个方法来将节点添加到列表的头部。那将是理想的

还可以阅读一些关于动态内存分配的内容。为了推动你,我提供了一些想法。阅读它,检查手册

例如,如果要动态分配节点。您可以这样做:-

struct node *tempNode;
tempNode = malloc(sizeof(struct node));
if(tempNode == NULL){
    fprintf(stderr,"%s","Error in malloc");
    exit(1);
}
..
...
无论您使用
malloc
分配什么,请在逻辑末尾释放它

大概

free(tempNode);
tempNode=NULL;

回答您的评论:-不要依赖未定义的行为。取消引用垃圾值会调用未定义的行为。您必须避免它,以使您的程序行为稳定


小事一桩

 struct Node currentNode = *cursor;
 printf("%d -->",currentNode.data);    
可以在一行中轻松完成

 printf("%d -->",cursor->data); //Also (*cursor).data


为什么在打印节点结构时要复制它们?为什么不直接使用指针呢?制作结构的本地副本毫无意义。您的错误在于
node4。下一步
是未定义的,因此当您到达列表的末尾时,您正在拾取一个未定义的值。如果该值不是
NULL
,您将尝试取消引用一个未定义的指针。@tomkarze,但当我注释while循环并通过方法printList调用时,代码是相同的。很好。我制作了用于调试的结构的本地副本,并记录了地址位置。请尝试理解<代码>节点4。下一步
将包含堆栈上发生的任何值。它可能是任何东西。这是未定义的行为。如果您编写这样的代码,您应该会遇到分段错误,并且无法可靠地预测它们。为什么在打印节点结构时复制它们?为什么不直接使用指针呢?制作结构的本地副本毫无意义。您的错误在于
node4。下一步
是未定义的,因此当您到达列表的末尾时,您正在拾取一个未定义的值。如果该值不是
NULL
,您将尝试取消引用一个未定义的指针。@tomkarze,但当我注释while循环并通过方法printList调用时,代码是相同的。很好。我制作了用于调试的结构的本地副本,并记录了地址位置。请尝试理解<代码>节点4。下一步
将包含堆栈上发生的任何值。它可能是任何东西。这是未定义的行为。如果您编写这样的代码,您应该期望得到分段错误,并且您将无法可靠地预测它们。但是,为什么即使node4 next没有分配给NULL,通过方法printList调用时它也能工作?@NavyCody.:检查答案..我修改了dit,这对解决主要问题非常有帮助,为什么通过方法printList调用时node3后面没有段错误。next=&node4;印刷品清单(标题)//这是有效的fine@NavyCody.:正在解释…您可以多次运行此代码…这是未定义的行为。它可能会在我的机器上爆炸,或者在你的机器上运行一次甚至更多,它会工作。在另一次运行中可能不会。这两个代码都是能够升级的代码。它是否与“函数声明打印列表将为其局部变量分配单独的内存堆栈,并且不会干扰主堆栈?”有关?我只是在测试它,以便以这种方式添加节点。但为什么它会