Is it safe to realloc memory allocated with new?
From what is written here, new
allocates in free store while malloc
uses heap and the two terms often mean the same thing.
From what is written here, realloc
may move the memory block to a new location. If free store and heap are two different memory spaces, does it mean any problem then?
Specifically I'd like to know if it is safe to use
int* data = new int[3];
// ...
int* mydata = (int*)realloc(data,6*sizeof(int));
If not, is there any other way to realloc
memory allocated with new
safely? I could allocate new area and memcpy
the contents, but from what I understand realloc
may use the same area if possible.
You can only realloc
that which has been allocated via malloc
(or family, like calloc
).
That's because the underlying data structures that keep track of free and used areas of memory, can be quite different.
It's likely but by no means guaranteed that C++ new
and C malloc
use the same underlying allocator, in which case realloc
could work for both. But formally that's in UB-land. And in practice it's just needlessly risky.
C++ does not offer functionality corresponding to realloc
.
The closest is the automatic reallocation of (the internal buffers of) containers like std::vector
.
The C++ containers suffer from being designed in a way that excludes use of realloc
.
Instead of the presented code
int* data = new int[3];
//...
int* mydata = (int*)realloc(data,6*sizeof(int));
… do this:
vector<int> data( 3 );
//...
data.resize( 6 );
However, if you absolutely need the general efficiency of realloc
, and if you have to accept new
for the original allocation, then your only recourse for efficiency is to use compiler-specific means, knowledge that realloc
is safe with this compiler.
Otherwise, if you absolutely need the general efficiency of realloc
but is not forced to accept new
, then you can use malloc
and realloc
. Using smart pointers then lets you get much of the same safety as with C++ containers.
The only possibly relevant restriction C++ adds to realloc
is that C++'s malloc
/calloc
/realloc
must not be implemented in terms of ::operator new
, and its free
must not be implemented in terms of ::operator delete
(per C++14 [c.malloc]p3-4).
This means the guarantee you are looking for does not exist in C++. It also means, however, that you can implement ::operator new
in terms of malloc
. And if you do that, then in theory, ::operator new
's result can be passed to realloc
.
In practice, you should be concerned about the possibility that new
's result does not match ::operator new
's result. C++ compilers may e.g. combine multiple new
expressions to use one single ::operator new
call. This is something compilers already did when the standard didn't allow it, IIRC, and the standard now does allow it (per C++14 [expr.new]p10). That means that even if you go this route, you still don't have a guarantee that passing your new
pointers to realloc
does anything meaningful, even if it's no longer undefined behaviour.