Ilan Aizelman WS
Ilan Aizelman WS

Reputation: 1632

Structures and lists what this code does when temp is null

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;
    }
}

Upvotes: 0

Views: 130

Answers (3)

John Bollinger
John Bollinger

Reputation: 180978

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.

Upvotes: 0

q.Then
q.Then

Reputation: 2751

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

Upvotes: 0

SGM1
SGM1

Reputation: 978

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).

Upvotes: 1

Related Questions