Using the std::realloc function:
If the new size is smaller, does it always have warranty to keep the memory block on the same position and only make it smaller, or it can move sometimes the whole block?
The reason to ask this, is that we'are writing a large and very hard code, and it is useful to make read only all the variables we need to leave unchanged, to obtain compiler's errors, when we try to change the wrong variable.
#include<cstdlib>
#include<iostream>
using namespace std;
int main(){
//From 10,000,000 unsigned ints to 10 unsigned ints
unsigned int * const array=new unsigned int[10000000];
cout<<array<<endl;
realloc(array,10*sizeof(unsigned int));
cout<<array<<endl;
delete array;
return 0;
}
Although I agree with the other answers in that you should not depend on it, there is an answer to be found in the glibc
source. (I am assuming that you are using glibc
, as you have not (yet) answered my comment asking which C library you are using)
EDIT: Using realloc
on memory allocated by new
is indeed disallowed, as other answers have mentioned.
mmap
If a block of memory is not allocated with mmap
, __libc_realloc calls the _int_realloc function, which contains the following snippet of code:
if ((unsigned long) (oldsize) >= (unsigned long) (nb))
{
/* already big enough; split below */
newp = oldp;
newsize = oldsize;
}
This makes the pointer to the new memory equal the pointer to the old memory and sets the size accordingly. Note the split below
comment; the old memory block may be resized to the requested size, but is not moved.
mmap
If the memory was internally allocated using mmap
, there are two ways of resizing the memory area; mremap_chunk
or a series of calls to malloc
, memcpy
and free
. If the mremap_chunk
function is available, it is used instead of the latter option.
mremap_chunk
The function mremap_chunk contains this snippet of code
/* No need to remap if the number of pages does not change. */
if (size + offset == new_size)
return p;
If the number of pages does not change from the old size to the new size, there is no need to remap and the old pointer is returned.
malloc
, memcpy
and free
If mremap_chunk
is not available, the __libc_realloc source continues with the following:
/* Note the extra SIZE_SZ overhead. */
if (oldsize - SIZE_SZ >= nb)
return oldmem; /* do nothing */
If the oldsize
variable minus the chunk size is more than or equal to the new size, just return the old memory.
Well then, here we are. In all cases, glibc returns a pointer to the old memory, not moving it (but possibly resizing it). If you are using glibc (and can somehow guarantee that the only C library you are using it with is glibc, and can guarantee that it won't change at some point in the future), you are able to rely on the behavior that realloc
does not move a block of memory if the requested size is equal to or less than the old size.