2017-02-28 97 views
0

尝试使用Fedora gcc下面的代码为简单链接列表添加新节点到列表尾部。编译没有错误。在执行期间,它显示分段错误,核心转储。 在MS Windows上,它正在工作。链接列表错误“分段错误”核心转储

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

struct Node 
{ 
    int data; 
    struct Node *next; 
}; 

void insertion(struct Node *); 
void display(struct Node *); 

int main(void) 
{ 
    struct Node *head; 
    head=NULL; 
    head->next=NULL; 

    int choice, cont; 

    do 
    { 
     printf("1.Insert  2.Display  3.Exit"); 
     scanf("%d",&choice); 

     if(choice==1) 
     { 
      insertion(head); 
     } 
     else if(choice==2) 
     { 
      display(head); 
     } 
     else if(choice==3) 
     { 
      exit(0); 
     } 
     else 
     { 
      printf("Wrong choice"); 
     } 
     printf("Continue? Press 1 otherwise 0:"); 
     scanf("%d",&cont); 
    }while(cont==1); 

    return 0; 
} 

void insertion(struct Node *start) 
{ 
    int data; 
    struct Node *temp=NULL; 
    temp->next=NULL; 
    struct Node *mnew=NULL; 
    mnew->next=NULL; 

    mnew=(struct Node *)malloc(sizeof(struct Node)); 

    printf("Enter data:"); 
    scanf("%d",&data); 

    mnew->data=data; 

    if(start==NULL) 
    { 
     start=mnew; 
    } 
    else if(start!=NULL && start->next==NULL) 
    { 
     start->next=mnew; 
    } 
    else 
    { 
     temp=start; 
     while(temp->next!=NULL) 
     { 
      temp=temp->next; 
     } 
     temp->next=mnew; 
    } 
} 

void display(struct Node *start) 
{ 
    struct Node *temp=NULL; 
    temp->next=NULL;  
    if(start==NULL) 
    { 
     printf("\nNothing to display!"); 
    } 
    else if(start!=NULL && start->next==NULL) 
    { 
     printf("%d",start->data); 
    } 
    else 
    { 
     temp=start; 
     while(temp!=NULL) 
     { 
      printf("%d",temp->data); 
      temp=temp->next; 
     } 
    } 
} 

您的帮助表示赞赏。

+1

时间来学习如何使用调试器。 –

+0

此外'start = mnew;'不会改变'head'的主要值.....你应该研究一些关于指针的东西。 – LPs

回答

2

仔细看看例如从insertion函数以下两行:

struct Node *temp=NULL; 
temp->next=NULL; 

第一个定义一个指针struct Node并使其为空指针。下一行你解引用这个空指针,这是无效的,并导致未定义的行为

你在多个地方都有同样的问题,两者完全一样,并且一般也取消引用空指针。

+0

...或OP可以使用'calloc'而不是'malloc' – LPs

+0

此外'start = mnew;'不会改变'head'主值 – LPs

+0

@LPs - 如果你建议'calloc'作为设置所有指针的快捷方式在结构为NULL时,知道零位模式不能保证是NULL指针的值。 [参见'calloc'标准注释](http://port70.net/~nsz/c/c11/n1570.html#note296)以供参考。 – StoryTeller

5
head=NULL; 
head->next=NULL; 

这段代码永远无法工作,就好像它是指向NULL(又名无处)您无法访问或赋值的head属性。

+0

我已经评论了第二行,现在正在执行。但插入3个节点后,显示功能报告“无显示!”这意味着开始仍然是NULL。 –

+0

这是因为你没有更新'head' - 你必须把它作为参考传入你的插入函数,或者让这个函数返回新的开始,这样你就可以把它分配给'head' –

+0

此外'start = mnew; '不改变'head'的主值 – LPs

1

您不能使用空指针访问数据。因此,此代码片段(以及类似的代码片段)

struct Node *head; 
head=NULL; 
head->next=NULL; 
^^^^^^^^^^^^^^^ 

无效。

至于函数insertion那么你必须通过引用传递头部。否则,该功能将处理头部的副本,并且功能中头部副本的任何更改都不会影响原始头部。

此外,如果内存分配将失败,则希望函数能够发出相关信号。因此,代替退货类型void,最好使用退货类型int

那么函数的声明可以像

int insertion(struct Node **); 
^^^   ^^^^^^^^^^^^^^ 

功能可以像

int insertion(struct Node **start) 
{ 
    int data; 

    printf("Enter data: "); 
    scanf("%d", &data); 

    struct Node *temp = (struct Node *)malloc(sizeof(struct Node)); 

    int success = temp != NULL; 

    if (success) 
    { 
     temp->data = data; 
     temp->next = NULL; 

     while (*start) start = &(*start)->next; 

     *start = temp; 
    } 

    return success; 
} 

的功能来定义可以被称为以下方式

insertion(&head); 

功能display能看起来像

void display(struct Node *start) 
{ 
    if (start == NULL) 
    { 
     printf("\nNothing to display!\n"); 
    } 
    else 
    { 
     for (; start; start = start->next) 
     { 
      printf("%d ", start->data); 
     } 
     putchar('\n'); 
    } 
} 
+0

我很惊讶为什么这甚至可以在Windows上工作?任何体面的编译器都应该能够捕捉到这个并提出警告。 –

0

如前面的注释,指向指向另一个NULLNULL指针未定义(导致指针应该保存地址)。 现在一些建议:

1)定义的结构如下所示:

typedef struct Node *node_pointer; 

这将使它更容易定义指针为结构。

2)

mnew=malloc(sizeof(*mnew)); //this is easier, and this should be before the ..->next=NULL; 

还检查是否分配成功:

if (!mnew) 
    return; //return something needed