C即使分配了内存,修改链表的程序也会导致分段错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C即使分配了内存,修改链表的程序也会导致分段错误相关的知识,希望对你有一定的参考价值。

对于我的程序,我必须从一个空的链表开始,并能够对它执行各种操作(即添加到开头,添加到结尾等)。我的列表结构如下

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

这是函数的开始,我已经分配空间并初始化列表,然后是while循环,其中case 1是添加到开始函数。对于此问题,可以忽略else部分。

printf("Who's ready to create and edit a linked list?
");
printf("Note: The list is currently empty, please choose option 1.
");
int choice, val, location, created;
struct node *llist;
llist = (struct node*)malloc(sizeof(struct node));
created =0;
while(choice != 8)
  {
    printf("      Operation Choices
");
    printf("1. Insert node at beginning
");
    printf("2. Insert node at end
");
    printf("3. Delete node from end
");
    printf("4. Delete node from beginning
");
    printf("5. Delete node from custom position
");
    printf("6. Insert node at custom position
");
    printf("7. Modify custom node
");
    printf("8. Exit
");
    scanf("%d", &choice);

    switch(choice) {
    case 1:
      printf("Value to enter: 
");
      scanf("%d", val);
      if(created == 0)
      {
        llist->num=val;
        llist->next = NULL;
        created = 1;
      }
      else
      {
        struct node *temp;
        temp = (struct node*)malloc(sizeof(struct node));
        temp = llist;
        free(llist);
        llist = (struct node*)malloc(sizeof(struct node));
        llist->num=val;
        llist->next=temp;
        free(temp);
        showlist(llist);
      }
    break;
  }
}

}

选项当前为'0',表示我没有向列表添加任何值,并且if部分正在执行。当我运行代码并尝试添加我的第一个值时,即使分配了内存,我仍然会遇到分段错误。我错过了什么?

知道为什么这个打印功能也不起作用?

void showlist(struct node *list)
{
 do{
   printf("%d->", list->num);
   list = list->next;
 }
 while(list->next != NULL);
}
答案

检查你的scanf()你需要把&val而不是val

对于其他部分,你为什么要释放llist的记忆?您可以直接检查列表是否为null,而不是检查创建的变量。在这种情况下,我建议使用Head节点。然后,您可以轻松地将当前节点的next指定为指向先前添加的节点,并将头节点的next分配给当前添加的节点。

另一答案

对于初学者:

scanf("%d", val);

这会将用户键入的值存储到val指定的地址中,此时此位置未定义。您想将其存储在val的地址中。

应该:

scanf("%d", &val);

而你的“其他”条款需要做很多工作。它可以简化为:

  else
  {
    struct node *insertnode = (struct node*)malloc(sizeof(struct node));
    insertnode->num = val;
    insertnode->next = llist;
    llist = insertnode;
  }

现在让我们清理你的整个功能。

第一步。只需在程序启动时将llist初始化为NULL并删除created变量。

struct node *llist = NULL;

然后你的case 1,即创建一个新节点并将其插入头部就是这样:

case 1:
{
    /* create a new node and make it the new head of the list */
    struct node* insertnode = (struct node*)malloc(sizeof(struct node));
    printf("Value to enter: 
");
    scanf("%d", &(insertnode->val));
    insertnode->next = llist; /* next points to the existing head, which will be null on first call */
    llist = insertnode; /* head now points to the new node*/

    break;
}
另一答案

有很多问题。除了selbie(第一编辑)说的还有其他几个: -

  1. 你理解事情的运作方式存在问题。比如你已经写过了 temp = (struct node*)malloc(sizeof(struct node)); temp = llist; 这是内存泄漏。为什么需要这个?因为您想添加新节点。但你没有正确使用它。
  2. 代码的设计并不是我想说的那么好 - llist在循环外部分配了内存并且在内部进行了修改。为什么不在需要的地方分配内存?你可以改变它。
  3. 所以您可以将其修改为:-(这会将新节点添加到列表的头部) if(created == 0) { llist = malloc(sizeof *llist); llist->num=val; llist->next = NULL; created = 1; } else { struct node *temp; temp = malloc(sizeof *temp); temp->num=val; temp->next=llist; llist = temp; showlist(llist); } 那些为malloc铸造的人不需要。当然,你可以检查malloc的返回值。完成整个列表后,释放这些记忆。
  4. 简单地说,showList函数会是这样的 void showlist(struct node *list) { while(list) { printf("%d->", list->num); list = list->next; } }

以上是关于C即使分配了内存,修改链表的程序也会导致分段错误的主要内容,如果未能解决你的问题,请参考以下文章

用于在C中为二叉搜索树分配内存的分段错误

由于 C 中的内存不足导致的分段错误

静态链表和动态链表的区别

C ++释放共享库中动态分配的内存导致崩溃

即使正确初始化,C结构也会打印错误的值

为啥释放内存会导致分段错误?