Here's what is really going on.
Let's take this example of some memory allocations packed together:
| some memory (10 bytes) | A (5 bytes) | unallocated (10 bytes) |
When you call realloc(A, 15)
in the above scenario the system is able to expand the allocated memory at the same location:
| some memory (10 bytes) | A (15 bytes) |
However, what happens in the following case?
| some memory (10 bytes) | A (5 bytes) | some memory (10 bytes) |
This time, realloc(A, 15)
can't simply expand the previously allocated region of memory since the latter 10 bytes it needs to expand A
are currently allocated.
Instead, it has to do the equivalent of malloc()
-ing a new memory region of 15 bytes and copying the original 5 bytes from A
's old memory region to the first 5 bytes of the new region.
In that case, realloc()
has not just expanded your memory allocation, but it has also moved the memory to a location where it can contiguously exist.
There are a few other reasons why realloc()
would move memory (not just size requirements) but a lot of those are implementation defined.
Due to the possibility of a memory move, realloc()
returns the address of the new pointer. As demonstrated above, sometimes it's the same pointer, and sometimes it's a new pointer.
When a move occurs, the old pointer is no longer valid as it is free()
'd by the system. If you try to access it, you'll receive an access violation/segmentation fault.
In your example, you're realloc()
-ing the memory in addValue()
but you're never updating the caller's pointer. When the caller goes to use the old pointer, if a move occurred in addValue()
, then the memory it tries to use will thus be invalid and the whole thing will crash and burn.
One way you could solve this is to pass a pointer to a pointer.
void addValue(int **A, int *n, int Data)
{
*A = realloc(*A, (*n+1)*sizeof(int *));
(*A)[*n] = Data;
(*n)++;
}
And call it appropriately:
addValue(&A, &nA, temp);
A final note: In C, you don't need to cast the result of malloc()
or realloc()
- unlike C++, void*
is implicitly cast-able to any other pointer type.