4

This is out of curiosity, I tried to find answers to my doubt on previous questions but they don't seem to have answer to it. So asking here, I just wrote a code where I am trying to allocate memory to an int pointer (to fill up an array) and scan int values to it. Once I am done with the array, I want to delete the data/memory allocated to the pointer. Although my code works fine and everything, why am I still able to see values inside int array even after freeing the pointer. Whereas, if I use free twice it throws up an error (which was expected after single use of free). Isn't this an odd behavior ? I tried it on my mac using Xcode also on codechef, same behavior, why ?

int *num=(int *)malloc(n*sizeof(int));
int i;
for(i=0;i<n;i++)
{
    scanf("%d",&num[i]);        
}    

for(i=0;i<n-1;i++){
    temp = some_function(x);        
}

free(num); 

for(i=0;i<n;i++)
{
    printf("\nnum[%d]= %d\n",i,num[i]);        
}

The above code prints values inside num[] which ideally it shouldn't.

4 Answers4

10

This is not odd, or wrong. When calling free on a pointer, you only tell the memory manager that it can re-use that portion of memory again for another malloc call. It won't erase the contents (this would take extra time with no function whatsoever). But, you can access it, because the pointer still points to a valid address. It leads to undefined behaviour though, because the memory manager could have given that memory to some other piece of code.

Calling free a second time can generate an error, because the memory manager doesn't know that pointer anymore as being valid (you just freed it!). In fact, this is undefined behaviour.

Bart Friederichs
  • 33,050
  • 15
  • 95
  • 195
  • Ok so what you are saying is using 'free' for the first time and then accessing array elements did not lead to _undefined behavior_, while using it twice and then accessing array elements did so. In any case, ideally this should not be the case, what is the best way to prevent this kind of situation from happening ? As in, if another user tries to access the stale data, how to prevent that ? – CodeInfinity Jun 17 '16 at 07:27
  • @CodeInfinity accessing the freed memory leads to undefined behaviour. "Undefined" does not mean that it will throw an error or crash. – Bart Friederichs Jun 17 '16 at 07:31
  • @CodeInfinity How would "another user" try to access that data? You can prevent this from happening by doing good memory management in your application, or move to a language that does that for you (e.g. Java, C#). – Bart Friederichs Jun 17 '16 at 11:16
  • A memory allocator may allocate the memory so that it is returned to the operating system after `free` (mmap/munmap on linux). – J.J. Hakala Jul 08 '16 at 03:41
6

Your program is being naughty and engaging in undefined behaviour.

The memory is indeed returned to the system after the first free, it's just that freeing memory:

  1. doesn't necessarily clear it
  2. doesn't necessarily prevent you from accessing it

Freeing it again throws an error, as you've already released it back to the system.

This doesn't mean you can just malloc memory, free it again, and rely on still being able to access it later!

Firstly, the behaviour you are seeing is undefined - according to the C standard your program is not really valid. With your particular combination of compiler, operating system and environment you still have access to the contents of that memory after free, but it could just as easily break. Additionally, "undefined behaviour" allows compilers to get up to all sorts of shenanigans, making later code not do what you're expecting at all.

Secondly, at any point after the free, the memory is available for subsequent mallocs. So even if you rely on the behaviour of your compiler/os/environment not breaking your use-after-free code, various other processes might fill that space with other stuff.

Use-after-free is a pretty big nono, so just free it once, and never access freed memory.

See: https://cwe.mitre.org/data/definitions/416.html for the types of security problems you can run into.

kibibu
  • 6,115
  • 1
  • 35
  • 41
1

The behaviour of your program is undefined.

Once you call free, you should no longer attempt to read that memory. Note the behaviour on calling free again on the same pointer is also undefined: don't do it!

There's no reason for the C runtime to be over-zealous and somehow disallow you explicitly from doing what you're doing as that would be suboptimal in well-written C programs.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1

Once you have called free(), you have indicated to memory manager that you are done with this memory. The memory manager can now use this memory to handle new allocation requests.

If you are accessing the same memory again since you already have a pointer to the memory location, this is an undefined behavior.

Calling free() again on the same memory location is also an undefined behavior.

Sumit Trehan
  • 3,985
  • 3
  • 27
  • 42