0

I just started studying linked list, and I tried to paint to understand it, and most of it I did, but I tackled with something strange, here's the piece of code I didn't understand:

If the allocation memory failed, what does this code do? and why do I need it? Can't I just free(temp) and that's it?

while(Head!=NULL)
    {
     temp=Head; 
     Head=Head->next;
     free(temp);
    }

Here's the complete code:

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

struct Worker
{
    int id;
    char name[21];
    struct Worker *next;
};

#define NUM 10

void main()
{
    int i, id_to_del;
    struct Worker *temp, *prev;
    struct Worker *Head = NULL;
    printf("Enter %d worker details:\n", NUM);
    for (i = 0; i < NUM; i++)
    {
        temp = (struct Worker *)malloc(sizeof(struct Worker));
        if (temp == NULL)
        {
            printf("Error allocating memory for worker #%d!", i + 1);
            while (Head != NULL)
            {
                temp = Head;
                Head = Head->next;
                free(temp);
            }
            exit(1);
        }
        printf("Worker #%d: ", i + 1);
        scanf("%d", &temp->id);
        gets(temp->name);
        temp->next = Head;
        Head = temp;
    }
}
Jonathan Leffler
  • 666,971
  • 126
  • 813
  • 1,185
Ilan Aizelman WS
  • 1,552
  • 17
  • 35
  • It runs trough the nodes in the list that were already allocated and de-allocates that memory before exiting. Since malloc failed, that particular node does not need to be freed. – Unimportant Apr 15 '16 at 17:52
  • Aside: `void main()` --> `int main(void)` – Weather Vane Apr 15 '16 at 17:54
  • @user1320881 what is head = head->next. what is head->next? – Ilan Aizelman WS Apr 15 '16 at 17:57
  • 1
    `Head`is the first node in the list. Each node contains a int `id`, a string `name` and a pointer to the next node in the list `next`. `Head` is saved in `temp`, then `Head` is made to point to the next node in the list, then the old head, pointed to by `temp` is de-allocated and repeat until the list is gone. – Unimportant Apr 15 '16 at 17:58
  • `head->next` points to the next item in the linked list. This is the link. So `head = head->next` is the iterator. – Weather Vane Apr 15 '16 at 17:59
  • Still didn't get it. also, after we free(temp), we don't have temp anymore, how can we free it again? – Ilan Aizelman WS Apr 15 '16 at 18:13
  • Temp is a pointer, pointing to the memory to be freed. Each loop temp is made to point to the next node in the list so that node can be freed – Unimportant Apr 15 '16 at 18:17
  • Note [What should `main()` return in C and C++](http://stackoverflow.com/questions/204476/). – Jonathan Leffler Apr 15 '16 at 18:17

3 Answers3

1

As user1320881 was saying, the piece of code runs though the list and deallocates it head first to last.

So A > B > C woud call free(A) then free(B) then free(C)

If a malloc had failed that pointer would be set to NULL (Link: http://linux.die.net/man/3/malloc)

Freeing a NULL pointer has no effect.

EDIT:

Head-> next you would expect to be the pointer to the next "worker".

So the outer loop (for(i=0; i<NUM; i++)...) populates the fields for each worker, using user input. If there is an allocation failure it frees the entire list (would prevent memory leaks when the program continues) and exits the program (which is unnecessary when exiting to program, but still good practice in my opinion).

SGM1
  • 918
  • 1
  • 10
  • 22
  • what is head = head->next. what is head->next? – Ilan Aizelman WS Apr 15 '16 at 17:57
  • @IlanAizelmanWS Are you familiar with any other programming language,? Pointers tend to be more difficult idea to grasp or get used to when coming from a language like Java, Python, etc. – SGM1 Apr 15 '16 at 18:10
0

malloc() does not signal the kernel to terminate execution of the current process of the code. Upon failure, malloc simply returns a NULL pointer with no effect on the program flow. free can never fail (for NULL pointers) and free()ing a NULL pointer has no effect.

Added note:

In most cases, the cast is not needed for malloc call in the current versions of C

q.Then
  • 2,691
  • 1
  • 16
  • 29
  • `free()` does not return a result code, but it certainly *can* fail. This ordinarily crashes your program. It happens when its argument is not a pointer to the start of an allocated block, or when the memory manager's internal data structures have been corrupted. – John Bollinger Apr 15 '16 at 18:09
  • Thanks, I just noticed that. I meant freeing a `NULL` pointer can't fail, but certainly yes `free` absolutely can fail – q.Then Apr 15 '16 at 18:10
0

The code block frees each node in a linked list, one at a time. Each node has a pointer, named next, to the subsequent node in the list -- this is what makes the aggregate a "linked list". The syntax Head->next means the same thing as (*Head).next: it is the member named 'next' of the struct Worker to which Head, a pointer, points.

The code must use a temporary variable because once a block is freed, you can no longer dereference pointers to it -- for instance, to get the next pointer that used to reside there. It tests for NULL because this is how it recognizes that there are no more nodes; it gets the NULL from either the original head node (in the case of an empty list) or from the next pointer of the last node. It sets a new value for that temporary variable at every iteration of the loop. Note, too, that free() does not free variables, pointers or otherwise; rather, it frees the dynamically-allocated memory to which pointers point. That makes the pointer's value useless, but it does not affect the pointer itself.

The nodes must be freed one at a time because that's the way dynamic allocation works. Each allocation must be matched with a separate free. And the free() function cannot automated this in a case such as yours because

  1. The free() function does not know any details about the contents of the block, such as which bytes constitute pointers,
  2. and even if it did, it would not be safe for it to free memory recursively, because pointers in the block it's freeing don't necessarily point to memory that is ready to be freed or even can be freed.
John Bollinger
  • 121,924
  • 8
  • 64
  • 118