【问题标题】:C Program for modifying linked list causes segmentation fault even though memory is allocated即使分配了内存,用于修改链表的 C 程序也会导致分段错误
【发布时间】:2018-08-10 07:20:47
【问题描述】:

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

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

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

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

    switch(choice) {
    case 1:
      printf("Value to enter: \n");
      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;
  }
}

}

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

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

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

【问题讨论】:

  • temp = llist; free(llist); 为什么?
  • Temp 包含整个列表,所以我想我应该释放内存来创建新的第一个节点。如果没有 free(llist),它仍然会产生分段错误。
  • @ebagl temp 不包含整个列表,temp 包含列表中第一个节点的地址。然后free(llist) 释放列表中的第一个节点。
  • temp = (struct node*)malloc(sizeof(struct node)); temp = llist; 这是内存泄漏。您将malloc 空间用于temp,然后将temp 重新分配给不同的值而不保存其原始值。这段记忆现在悬而未决,没有任何引用。
  • 那么不应该为'temp'分配内存吗?我也试过了,但没有成功。

标签: c linked-list segmentation-fault


【解决方案1】:

对于初学者:

scanf("%d", val);

这会将用户键入的值存储到val 指定的地址 中,此时未定义。你想把它存储在valval的地址

应该是:

scanf("%d", &val);

你的“else”子句需要做很多工作。可以简化为:

  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: \n");
    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;
}

【讨论】:

  • 为此+1,现在很累。函数的else部分现在不工作了,你能看出是什么问题吗?
  • 我不知道您在回答,所以我添加了您的答案作为您当时讨论的scanf 问题的参考。现在看来您编辑了整个答案。
  • 我会说我的答案是持续集成的结果。
  • 这向我展示了我的方式中的缺陷,很好的修复。感谢您帮助这位显然是新手的程序员。
  • 如果您觉得答案有用,别忘了点赞和/或接受它。
【解决方案2】:

检查您的scanf(),您需要输入&val 而不是val

对于else部分,你为什么要释放llist的内存?您可以直接检查列表是否为null,而不是检查创建的变量。 在这种情况下,我会建议使用Head 节点。然后就可以很方便的将当前节点的next赋值给之前添加的节点,并将头节点的next赋值给当前添加的节点。

【讨论】:

  • 在我将head-> 分配给下一个元素之后,我的列表会不会以结构head 而不是llist 开头?
  • 不要将head 分配给下一个元素。做这样的事情:head->next = *CurrentlyAddedNode 然后调用head 节点显示
【解决方案3】:

有很多问题。除了 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; 
        }
    }
    

【讨论】:

  • @ebagl.:检查。
  • 那个打印函数产生分段错误...我迷路了
  • @ebagl.: 你已经按照我的建议修改了代码?对于这两种修改?
  • @ebagl.: 干得好。回答有帮助吗?
  • @ebagl 由于 coderredoc 帮助了您,因此对答案进行投票和/或接受它是一种很好的方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-04
  • 2023-01-03
  • 1970-01-01
  • 2018-06-28
  • 1970-01-01
  • 1970-01-01
  • 2017-11-21
相关资源
最近更新 更多