-5

I have two questions.

  1. How does the free function in C work?
  2. How come the pointer variable updates itself to store the new address?

This is my code:

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

int main()
{
    int a;
    int *p;
    p = (int *)malloc(sizeof(int));
    *p = 10;
    int *q = p;
    printf("p:%d\n", p);
    printf("q:%d\n", q);
    printf("*p:%d\n", *p);
    printf("*q:%d\n", *q);
    free(p);
    printf("Memory freed.\n");
    p = (int *)malloc(sizeof(int));
    *p = 19;

    printf("p:%d\n", p);
    printf("q:%d\n", q);
    printf("*p:%d\n", *p);
    printf("*q:%d\n", *q);
}

How come the output is like this?

p:2067804800
q:2067804800
*p:10
*q:10
Memory freed.
p:2067804800
q:2067804800
*p:19
*q:19
fluter
  • 13,238
  • 8
  • 62
  • 100
Brevis Iunius
  • 349
  • 1
  • 2
  • 8
  • 1
    You have two cases of *undefined behavior*. The first because you use the wrong format to print a pointer, you should be using `"%p"` to print pointers. See e.g. [this `printf` (and family) reference](http://en.cppreference.com/w/c/io/fprintf). The second UB is because you dereference `q` after freeing the memory it point so. There is no guarantee that the behavior you see will happen again. Once you free the memory, you must not dereference a pointer pointing to that memory. – Some programmer dude May 09 '16 at 07:50
  • The output is "like this" because **this** is what you've asked it to be (i.e., this is what your program prints). Please specify exactly what you think should be different than what you've posted. BTW, in plain English, the title of your question makes zero sense. – barak manos May 09 '16 at 07:50
  • As for the "the pointer variable updates itself to store the new address" issue. It *doesn't*. You explicitly do `p = malloc(...)` which is the whole "update" to the variable. What you're doing is no different than e.g. `int a = 10; a = 20;` – Some programmer dude May 09 '16 at 07:53
  • it is said that you needn't cast the return value of malloc. – machine_1 May 09 '16 at 07:53
  • Lastly, [in C you should not really cast the result of `malloc`](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc), or any other function returning `void *`. – Some programmer dude May 09 '16 at 07:53
  • @machine_1: You should make that as a *side note*, as it doesn't directly answer the question at hand, and it only adds confusion to the (already pretty confused) OP. – barak manos May 09 '16 at 07:54
  • I'm voting to close this question as off-topic because I think questions of the 'how does it work' variety are off-topic for SO – Strawberry May 09 '16 at 11:00

2 Answers2

6

Once you call free() on a malloc()-ed pointer, the memory (returned pointer) is free to be re-allocated by any subsequent call to malloc() family. That's the whole point of having free().

Quoting C11, chapter §7.22.3.3

The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. [....]

So, it is quite possible, that after free(), when you malloc()-ed again for the same pointer for same amount of memory, the same pointer is returned. There's no surprise.

(And who knows, if your compiler is smart enough, it can actually remove the ineffective free(p); and p = (int*)malloc(sizeof(int)); altogether)

Next, in the very last line of your code,

 printf("*q:%d\n", *q);

you invoke undefined behavior by attempting to access (dereference) already free-d memory. Don't do that.

That said,

  1. To print a pointer, you should use %p format specifier and cast the argument to void*.
  2. Please see this discussion on why not to cast the return value of malloc() and family in C..
Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
1

malloc() gives virtual address, so it is not surprising that the system will give you back the same address, since you're asking for the same amount of memory.

q doesn't update itself to store the new value of p. If you delete the free(p); before the p = malloc(..., p will get a new address, while the q will still having the old address.

raymai97
  • 806
  • 7
  • 19