user4032676
user4032676

Reputation:

Little bit confusing about free pointer inside function

some weeks ago I learn about proper way how pointers should be allocated and dealocated inside function so given in example linkedList:

typedef struct _node {
    void *data;
    struct _node *next;
} Node;

typedef struct _linkedList {
    Node *head;
    Node *tail;
    Node *current;
} LinkedList;

In My opinion right way to destroy queue is by using function that get pointer to pointer to node which I want to delete:

void destroy (Node ** node) 

Or in more real world example pointer to pointer and pointer to list to delete.

void destroy (LinkedList * list, Node ** node) 

but now I am reading book "Understanding C pointers" and I encounter to problem because In chapter 6 pointers to structures there is followed example of function destroyList:

void delete(LinkedList *list, Node *node) {
    if (node == list->head) {
        if (list->head->next == NULL) {
            list->head = list->tail = NULL;
        } else {
            list->head = list->head->next;
        }
    } else {
        Node *tmp = list->head;
        while (tmp != NULL && tmp->next != node) {
            tmp = tmp->next;
        }
       if (tmp != NULL) {
            tmp->next = node->next;
        }    
    }   
    free(node);  //free on pointer copy value not pointer
}

So in this example author run free on pointer that is passed by value, so in my opinion this shouldn't work. But I looked into errata and there is no notes about this example.

In this case I understand that List is function argument to use correct instance of list, but is should be rather that:

free(list->head) ; //It should work?

And then also free memory for allocated List.

Am I right? Because reading this example I have a feeling that I have a problem with good understanding of this topic.

Also I went to Linux Man Page and I saw free prototype:

 void free(void *ptr);    // http://linux.die.net/man/3/free

So why everybody told to pass pointer to pointer when You want to free memory but in standard library same free function take as parameter not pointer to pointer but pointer, how it work correctly?

Upvotes: 2

Views: 1699

Answers (3)

blh83
blh83

Reputation: 495

I'll do my best to try and clarify here. When you are freeing memory, you are supposed to free the actual memory that was allocated. When you call a function like malloc, you are expected to give the size of data you want to malloc. In your case, 'node' would have been malloced like 'malloc(sizeof(node))'.

Again, when you call free, you are intending to free the entire block of memory that was allocated. If you were to free a pointer to the memory, you haven't actually freed the memory, but instead freed the thing pointing to it. Now you have leaked memory because nothing can access the malloced node anymore.

So in the code you cited, he isn't freeing the value of node, he is freeing the memory allocated to node. When he calls free(node) he is passing to free a pointer to the node (because a node pointer was passed to the function), and free then releases that memory for node.

Upvotes: 0

Ingo Leonhardt
Ingo Leonhardt

Reputation: 9904

as you state correctly, free( void *p ) frees the memory p points to but as the address is passed by value it will remain unchanged for the caller. Thus you could run into problems like this:

int *p = malloc( sizeof *p );

*p = 1;
free( p );
...

if( p )
   *p = 2;     // Undefined Behaviour!!! although p is free()'d it's still != NULL

So you will often find

free( p );
p = NULL;

Nevertheless in my opinion it's ok to write a free() like function where you pass a pointer by value as long as the function's description states clearly that the pointer must not be used afterwards (no matter wht type of pointer that may be). But of course you're free to define the function with double pointers and set everything you have free()'d to NULL inside, like in this very simple example:

void myfree( void **pp )
{
   free( *p );
   *p = NULL;
}

...
int *p = malloc( sizeof *p );
...
myfree( &p );
// now p == NULL

Upvotes: 2

R Sahu
R Sahu

Reputation: 206717

You don't need to use:

void destroy (LinkedList * list, Node ** node) 

Using

void destroy (LinkedList * list, Node * node) 

is sufficient.

You can use:

void destroy(int* pointer)
{
   free(pointer);
}

int* ip = malloc(sizeof(int));
destroy(ip);

to free memory allocated by malloc and related functions.

Using

void destroy(int** pointer)
{
   free(pointer);
}

int* ip = malloc(sizeof(int));
destroy(&ip);

is wrong.

You can use:

void destroy(int** pointer)
{
   free(*pointer);
}

int* ip = malloc(sizeof(int));
destroy(&ip);

but that uses additional & and * that are not necessary.

Upvotes: 0

Related Questions