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

int main()
{

    int *a;
    a = (int *)malloc(100*sizeof(int));
    int i=0;


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

    a = (int*)realloc(a,75*sizeof(int));

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

    free(a);

    return 0;

}

In this program I expected the program to give me a segmentation fault because im trying to access an element of an array which is freed using realloc() . But then the output is pretty much the same except for a few final elements !

So my doubt is whether the memory is actually getting freed ? What exactly is happening ?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
Thejas
  • 59
  • 5
  • 3
    First of all, [in C you should not cast the result of `malloc` and family](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). Secondly, accessing beyond the limits of allocated memory leads to [*undefined behavior*](http://en.wikipedia.org/wiki/Undefined_behavior), meaning anything could happen. Finally, don't reassign to the same pointer you reallocate, remember that if `realloc` fails it will return `NULL` and you will loose the original pointer. – Some programmer dude Sep 29 '14 at 07:12
  • Thank you Joachim :) Will definitely look after that . – Thejas Sep 29 '14 at 08:12

3 Answers3

3

The way realloc works is that it guarantees that a[0]..a[74] will have the same values after the realloc as they did before it.

However, the moment you try to access a[75] after the realloc, you have undefined behaviour. This means that the program is free to behave in any way it pleases, including segfaulting, printing out the original values, printing out some random values, not printing anything at all, launching a nuclear strike, etc. There is no requirement for it to segfault.

So my doubt is whether the memory is actually getting freed?

There is absolutely no reason to think that realloc is not doing its job here.

What exactly is happening?

Most likely, the memory is getting freed by shrinking the original memory block and not wiping out the now unused final 25 array elements. As a result, the undefined behaviour manifests itself my printing out the original values. It is worth noting that even the slightest changes to the code, the compiler, the runtime library, the OS etc could make the undefined behaviour manifest itself differently.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
0

Accessing an array beyond its bounds is undefined behaviour. You might encounter a runtime error. Or you might not. The memory manager may well have decided to re-use the original block of memory when you re-sized. But there's no guarantee of that. Undefined behaviour means that you cannot reason about or predict what will happen. There's no grounds for you to expect anything to happen.

Simply put, don't access beyond the end of the array.

Some other points:

  1. The correct main declaration here is int main(void).
  2. Casting the value returned by malloc is not needed and can mask errors. Don't do it.
  3. Always store the return value of realloc into a separate variable so that you can detect NULL being returned and so avoid losing and leaking the original block.
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

You may get a segmentation fault, but you may not. The behaviour is undefined, which means anything can happen, but I'll attempt to explain what you might be experiencing.

There's a mapping between your virtual address space and physical pages, and that mapping is usually in pages of 4096 bytes at least (well, there's virtual memory also, but lets ignore that for the moment).

You get a segmentation fault if you attempt to address virtual address space that doesn't map to a physical page. So your call to realloc may not have resulted in a physical page being returned to the system, so it's still mapped to you program and can be used. However a following call to malloc could use that space, or it could be reclaimed by the system at any time. In the former case you'd possibly overwrite another variable, in the latter case you'll segfault.

Clinton
  • 22,361
  • 15
  • 67
  • 163