0

I've been running some tests trying to understand how the free() function works. Here is my code followed by some questions based on what I have understood.

int n=0,i=0;
scanf("%d",&n);
int *A = (int*)malloc(n*sizeof(int));
for (i=0;i<n;i++)
{
    A[i]=2*i;
    printf("A[%d] = %d\n",i,*(A+i));

}
printf("Address of A is = %d\n",A);
free(A);
for (i=0;i<n;i++)
{
    printf("%d\n",*(A+i));

}
printf("Address of A is = %d\n",A);

What I don't understand is why after free(A), the values of A are still the same? Shouldn't there be some garbage value after free? And why did the address of A remain the same? What really happened after freeing A in terms of memory?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Kamoukou
  • 123
  • 1
  • 2
  • 6
  • Why shouldn't they be? If you put trash in the can, it does not vanish until the cart takes it away, or the neighbour replaces it with some rocks. `free` does not deliberately trash the memory that is released. That happens when some other process is assigned the same memory. Also the address of `A` remains the same. `free` cannot change that. If you want to invalidiate it you must assign `A = NULL` yourself. – Weather Vane Oct 21 '16 at 19:44
  • But what I don't understand, is why you are accessing memory that you told the system is no longer yours, and expect any meaningful results. – Weather Vane Oct 21 '16 at 19:50
  • 2
    Why would you expect the memory to change? If you take a piece of paper from a note pad, write a note on it, and then throw the paper in the trash can, the writing on the note doesn't magically disappear from the page. – Ken White Oct 21 '16 at 19:52
  • 2
    Note that the correct way to print a pointer uses the `"%p"` conversion specification (and casts the argument to `void *`), or uses a cast to `uintptr_t` (from ``) and a conversion specification such as `"0x%.16" PRIXPTR`. You only get away with using `%d` when `sizeof(int) == sizeof(void *)`, which is often true on 32-bit systems. – Jonathan Leffler Oct 21 '16 at 19:55
  • 1
    @KenWhite: That analogy can be extended even further and it still works - The writing doesn't disappear, but if you throw out a note so large you have to empty the trash can (return memory to OS), it may as well have. The note might still have the writing on it, but you can't read it, because it's inside a garbage truck (the OS managed memory pool) and the garbage men won't let you climb on inside to check (you lack read access to memory not owned by your process). If you try, they garbage men beat you senseless (seg fault). :-) – ShadowRanger Oct 21 '16 at 19:56
  • "Shouldn't there be some garbage value after free?" It *is* a garbage value. Garbage doesn't always look like random junk. Sometimes it looks familiar, especially if you yourself just tossed it in the trash. – John Coleman Oct 21 '16 at 20:25

1 Answers1

3

free returns the memory to the heap. It doesn't say anything about what it does with the contents of the memory, and in fact, the usual behavior is "it doesn't do anything" (that is, it performs no reads or writes of the data itself, just updates the heap tracking info to mark that memory as available for reuse or gives it back to the OS).

You shouldn't rely on this though; use-after-free is undefined behavior, so it can do anything it wants to. In practice, reading large allocations immediately after freeing will likely seg fault, while small allocations will continue to work until new mallocs reuse the space, but you cannot rely on any of this, and it's system and use pattern specific.

If you access freed memory, you're doing it wrong, and it will eventually bite you.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271