Why does reallocating with realloc, a pre-allocated memory using allocator::allocate conserve the old start memory address?

Viewed 45

The main problem was reallocating memory while expanding it and conserving data and the first starting memory address which is used by many other parts of the program (such as a static starting memory)

This doesn't work with realloc because he deallocate the precedent allocated memory and affects another with a new starting memory address:

 using namespace std;

 int *t = static_cast<int*>(malloc( 2*sizeof(int)));
   cout << "address " << t << endl;

 t = static_cast<int*>(realloc(t,10*sizeof(int)));
   cout << "address " << t << endl;

=========================

 // both of the addresses are different
 address 0x55c454fc5180
 address 0x55c454fc55b0

after testing many solutions (even direct access to the memory by system call), I found this one :

 allocator<int> alloc;
 int *t = alloc.allocate(2*sizeof(int));
   cout << "address " << t << endl;

 // reallocating memory using realloc
 t = static_cast<int*>(realloc(t, 10*sizeof(int)));
   cout << "address " << t << endl;

=========================
 
 // now the addresses are the same 
 address 0x55c454fc5180
 address 0x55c454fc5180

I tried to explain how it's possible but not able to match the both functioning and I want to know why and how it works.

1 Answers

Using realloc on an address allocated with std::allocator, new or anything similar has undefined behavior. It can only be used when the address comes from the malloc/calloc/realloc family of allocation functions. Never mix them.

In general realloc does not guarantee that the address of the allocation remains unchanged. There is no guarantee that realloc will be able to expand the allocation in place (e.g. there might not be enough memory free after the current allocation). It is the defined behavior of realloc to copy the memory block to a new allocation where sufficient space is free in such a situation. This also means that realloc can only be used with trivially-copyable types in C++.

If your program depends on the address of the allocation remaining unchanged, then it can't expand the allocation. You can have one of these, not both.


Also, you are using std::allocator<int> wrong. The argument to .allocate should be the number of elements of the array to allocate, not the number of bytes. Then afterwards you are supposed to call std::allocator_traits<std::allocator<int>>::construct or std::construct_at or a placement-new on each element of the array to construct and start the lifetime of the array elements.

I am not sure why you are trying to use std::allocator here, but it is unlikely that you need it. If you just intend to create an array of int, you should use new int[n], not std::allocator. Or rather don't worry with manual memory management at all and just use std::vector<int>.

Related