Pat R Ellery
Pat R Ellery

Reputation: 1716

c free() works when I call but not in my function

I am learning C and I am playing with malloc and free. But for some reason when I use free() in the main everything works but when I put it in my function it does not

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

  struct st {
    int number;
  };
  void del(struct st *s) {
    if (s == NULL) return;
    free(s); s = NULL;
  }
  int main() {
    struct st *s;
    s = (struct st *)malloc(sizeof(struct st));
    s->number = 4;
    printf("The value is: %d", s->number);
    del(s);
  //  free(s); s= NULL;
    if(s == NULL) printf("\nThe struct is removed from memory\n");
    else printf("\nThe value is: %d\n", s->number);
    return 0;
  }

This echo:

The value is: 4
The value is: 0

But if I do:

   // del(s);
    free(s); s= NULL;

it works

Upvotes: 1

Views: 104

Answers (2)

Vatine
Vatine

Reputation: 21238

Your del function frees the allocated memory and assigns NULL to the local copy of the variable. However, the local copy is not the same copy as that at the call-site (even if both point to the same allocated object, that has been freed).

You then end up doing what's called "use after free()", which is (probably) not actively harmful in this specific case, but can be a crash bug in the general case (and possibly a vector for code injection and exploits).

Either re-write del to take a pointer to a pointer and pass &s in, or have del return "the new value" and do s = del(s).

Upvotes: 0

Michał Szydłowski
Michał Szydłowski

Reputation: 3409

You are passing the pointer to your function, which means it only has access to the local copy of this pointer. So your free(s) will free only this local copy. If you want to free a variable, that is outside of the scope of the function from which you call free, you need to gain access to it by derefering again (passing a pointer to this pointer).

void del(struct st **s) {
    if (*s == NULL) return;
    free(*s); 
    *s = NULL;
}

should work fine.

Edit: call the function by del(&s);

Upvotes: 2

Related Questions