Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

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(). So I strongly assume the error can be found in this 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. Do you know what I´m doing wrong?...

like image 655
Greta Avatar asked Nov 19 '19 09:11

Greta


People also ask

Can out of memory cause segmentation fault?

Overview. A segmentation fault (aka segfault) is a common condition that causes programs to crash; they are often associated with a file named core . Segfaults are caused by a program trying to read or write an illegal memory location.

What are the causes of segmentation fault?

The following are some typical causes of a segmentation fault: Attempting to access a nonexistent memory address (outside process's address space) Attempting to access memory the program does not have rights to (such as kernel structures in process context) Attempting to write read-only memory (such as code segment)

What is a memory leak What is a segmentation fault?

Memory Leaks (Wikipedia) Segmentation Faults: The most common reason for this type of error is trying to access a part of memory that either doesn't exist or is outside of the allowed memory of your running program (for example if you tried to access the memory the OS is loaded in).

Which pointer may cause segmentation fault when the memory is no longer available?

Here in the below code, the pointer p is dereferenced after freeing the memory block, which is not allowed by the compiler. So it produces the error segment fault or abnormal program termination at runtime.


2 Answers

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.

You need to set start to NULL after freeing.

   list_free(start);
   start = NULL;
   printf("Empty list:\n");
   list_print(start);
like image 70
kiran Biradar Avatar answered Nov 09 '22 06:11

kiran Biradar


The function list_free gets its argument by value. So the function deals with a copy of the original pointer to node. As a result the original pointer to node start stays unchanged.

And as a consequence the output of the list after calling the function 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.

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

list_free( &start );

After exiting the function the original pointer start will be equal to 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. He can make the same error as you did forgetting to set the pointer to NULL.

like image 35
Vlad from Moscow Avatar answered Nov 09 '22 06:11

Vlad from Moscow