简体   繁体   English

为什么释放 memory 会导致分段错误?

[英]Why does freeing the memory lead to segmentation fault?

I´m desperate because this code form time to time gives me a segmentation fault and I have no clue why.我很绝望,因为这段代码不时给我一个分段错误,我不知道为什么。 Actually it´s only supposed to add some linked list notes, print them and then empty the list by freeing the memory.实际上它只是应该添加一些链表注释,打印它们然后通过释放 memory 来清空列表。

struct int_list {
   int value;
   struct int_list *next;
};
typedef struct int_list IntList;


void list_print(IntList *start)
{
   IntList *cur = start;
   while(cur != NULL)
   {
      printf("%d\n", cur->value);
      cur = cur->next;
   }
}


void list_append(IntList **start, int newval)
{
   IntList *newel = malloc(sizeof(IntList));
   newel->value = newval;
   newel->next = NULL;

   if(*start == NULL)
   {
      *start = newel;
   }

   else
   {
      IntList *cur = *start;
      while(cur->next != NULL)
      {
          cur = cur->next;
      }

      cur->next = newel;
   }

}


void list_free(IntList *start)
{
   IntList *prev = start;                           // prev = start
   while (start != NULL)                            // if start != Null
   {
       start = start->next;                         // make start point to the next element
       printf("Deleting %d\n", prev->value);
       free(prev);                                  // delete the previous element
       prev = start;                                // make previous point to start again
   }
   printf("\n");
}


int main(int argc, char *argv[])
{
   // fill the list
   IntList *start = NULL;
   list_append(&start, 42);
   list_append(&start, 30);
   list_append(&start, 16);

   // print the list
   printf("\nList 1\n");
   list_print(start);
   printf("\n");

   // free the memory and print again
   list_free(start);
   printf("Empty list:\n");
   list_print(start);
   printf("\n");

}

Everything was working just fine before I tried to implement list_free().在我尝试实现 list_free() 之前,一切正常。 So I strongly assume the error can be found in this function.所以我强烈假设错误可以在这个 function 中找到。 Just posting the rest of the code as well because I´m new to structures and am not 100% sure about having handles them correctly.只需发布代码的 rest,因为我是结构新手,并且不能 100% 确定是否正确处理它们。 Do you know what I´m doing wrong?...你知道我做错了什么吗?...

You have undefined behavior because of dangling pointer由于悬空指针,您有未定义的行为

   list_free(start);

That is, start is still pointing to freed memory which you are trying to access.也就是说, start仍然指向您尝试访问的已释放 memory 。

You need to set start to NULL after free ing.您需要在free之后将start设置为NULL

   list_free(start);
   start = NULL;
   printf("Empty list:\n");
   list_print(start);

The function list_free gets its argument by value. function list_free按值获取其参数。 So the function deals with a copy of the original pointer to node.因此 function 处理指向节点的原始指针的副本。 As a result the original pointer to node start stays unchanged.结果,指向节点start的原始指针保持不变。

And as a consequence the output of the list after calling the function list_free因此,在调用 function list_free 之后,列表的list_free

list_free(start);
printf("Empty list:\n");
list_print(start);

has undefined behavior.具有未定义的行为。

The function should accept the original pointer to node by reference as the function list_append does. function 应该像 function list_append那样通过引用接受指向节点的原始指针。

For example例如

void list_free( IntList **start )
{
    while ( *start != NULL )
    {
        IntList *prev = *start;                     // prev = start
        *start = ( *start )->next;                  // make start point to the next element
        printf("Deleting %d\n", prev->value);
        free(prev);                                  // delete the previous element
    }

    printf("\n");
}

Call the function like像这样调用 function

list_free( &start );

After exiting the function the original pointer start will be equal to NULL .退出 function 后,原始指针start将等于NULL That is the list will be indeed freed.那就是列表确实会被释放。

This is better than when the client of the list shall explicitly set the pointer to NULL himself.这比列表的客户端自己显式设置指向NULL的指针要好。 He can make the same error as you did forgetting to set the pointer to NULL.他可能会犯与您忘记将指针设置为 NULL 相同的错误。

Pointer is still pointing to the memory location of the deallocated memory, which is also an instance of segmentation fault.指针仍然指向已释放的 memory 的 memory 位置,这也是分段错误的一个实例。 It is "undefined behavior" and can cause arbitrarily unpredictable things to happen as the contents of pointed location are unknown, varying runtime.这是“未定义的行为”,并且可能导致任意不可预测的事情发生,因为指向位置的内容是未知的,运行时间不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM