How can I call a constructor on a memory region that is already allocated?
You can use the placement new constructor, which takes an address.
Foo* foo = new (your_memory_address_here) Foo ();
Take a look at a more detailed explanation at the C++ FAQ lite or the MSDN. The only thing you need to make sure that the memory is properly aligned (malloc is supposed to return memory that is properly aligned for anything, but beware of things like SSE which may need alignment to 16 bytes boundaries or so).
Notice that before invoking placement new, you need to call the destructor on the memory – at least if the object either has a nontrivial destructor or contains members which have.
For an object pointer obj of class Foo the destructor can explicitly be called as follows:
obj->~Foo();
The placement new constructor mentioned by the accepted answer is an old way before the allocator class defined in header. Now you really should do(in C++11 style):
allocator<Foo> alloc;
//Allocate memory for one or n objects
auto p = alloc.allocate(1);
//Construct an object of Foo on allocated memory block p, by calling one of Foo's constructors
alloc.construct(p, args, ...);
//OK, p now points to a Foo object ready for use...
//Call Foo's destructor but don't release memory of p
alloc.destroy(p);
//Release memory
alloc.deallocate(p, 1);
That's it.
Related
I'm trying to implement a custom allocator for C++ that works on any form of new/delete/malloc/free. How my program works, I allocate at the start of the program a memory pool of x bytes and work with them. For example, when someone writes int* a= new int; my program will return the address from the memory pool which is available and marks it as allocated and that address along with the size allocated is removed from the memory pool. When someone writes delete a; the address is returned to the memory pool and can be used again. My problem is that I don't fully understand how new(placement) works and how should I deal with it, because when my function gets called to allocate memory on new/malloc I have as a parameter only the size of the memory the program needs and I just return an available address to that memory to be used. Consider the following example
auto p = (std::string*)malloc(5 * sizeof(std::string));
void * placement = p;
new(placement) std::string(4, (char)('a'));
std::cout<< *p;
On the first line my custom allocated will return to p an address from my memory pool where there is memory available of a total of 5* sizeof(std::string)), on the third line my custom allocator will allocate again memory returning another address. When I print *p it prints exactly what I was expected aaaa.
Is this how it should work?
A normal new does two things:
allocate storage; and
construct an object.
Now we want to separate these two steps. Allocating raw storage is easy, but there is no "native" way to construct an object at a given address in C++. Therefore, the new operator is overloaded to serve this purpose, by returning the given pointer for the first step.
We don't need a corresponding delete, because we can call the destructor manually. In C++17, std::destroy_at was added to the standard library. Since C++20, std::construct_at can be used to construct an object instead of placement new:
std::construct_at(p, 4, 'a');
The C++ Super-FAQ explains placement new very well:
What is “placement new” and why would I use it?
There are many uses of placement new. The simplest use is to place an
object at a particular location in memory. This is done by supplying
the place as a pointer parameter to the new part of a new expression:
#include <new> // Must #include this to use "placement new"
#include "Fred.h" // Declaration of class Fred
void someCode()
{
char memory[sizeof(Fred)]; // Line #1
void* place = memory; // Line #2
Fred* f = new(place) Fred(); // Line #3 (see "DANGER" below)
// The pointers f and place will be equal
// ...
}
Line #1 creates an array of sizeof(Fred) bytes of memory, which is
big enough to hold a Fred object. Line #2 creates a pointer place
that points to the first byte of this memory (experienced C
programmers will note that this step was unnecessary; it’s there only
to make the code more obvious). Line #3 essentially just calls the
constructor Fred::Fred(). The this pointer in the Fred
constructor will be equal to place. The returned pointer f will
therefore be equal to place.
ADVICE: Don’t use this “placement new” syntax unless you have to. Use it only when you really care that an object is placed at a
particular location in memory. For example, when your hardware has a
memory-mapped I/O timer device, and you want to place a Clock object
at that memory location.
DANGER: You are taking sole responsibility that the pointer you pass to the “placement new” operator points to a region of memory that is
big enough and is properly aligned for the object type that you’re
creating. Neither the compiler nor the run-time system make any
attempt to check whether you did this right. If your Fred class
needs to be aligned on a 4 byte boundary but you supplied a location
that isn’t properly aligned, you can have a serious disaster on your
hands (if you don’t know what “alignment” means, please don’t use
the placement new syntax). You have been warned.
You are also solely responsible for destructing the placed object.
This is done by explicitly calling the destructor:
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
// ...
f->~Fred(); // Explicitly call the destructor for the placed object
}
This is about the only time you ever explicitly call a destructor.
there are quite a few faces for the new operator in c++, but I'm interested in placement new.
Suppose you allocate memory at a specific memory location
int memoryPool[poolSize*sizeof(int)];
int* p = new (mem) int; //allocates memory inside the memoryPool buffer
delete p; //segmentation fault
How can I correctly deallocate memory in this case?
What if instead of built-in type int I would use some class called myClass?
myClass memoryPool[poolSize*sizeof(myClass )];
myClass * p = new (mem) myClass ; //allocates memory inside the memoryPool buffer
delete p; //segmentation fault
Thanks for your help.
In the first case, there's no point in using placement new, since int doesn't have a constructor.
In the second case, it's either pointless (if myClass is trivial) or wrong, since there are already objects in the array.
You use placement new to initialise an object in a block of memory, which must be suitably aligned, and mustn't already contain a (non-trivial) object.
char memory[enough_bytes]; // WARNING: may not be properly aligned.
myClass * c = new (memory) myClass;
Once you've finished with it, you need to destroy the object by calling its destructor:
c->~myClass();
This separates the object's lifetime from that of its memory. You might also have to release the memory at some point, depending on how you allocated it; in this case, it's an automatic array, so it's automatically released when it goes out of scope.
In your case there is no need to deallocate it, your int array will be deallocated once you return from your function. You should only call explicitly your destructor:
p->~myclass();
to keep you buffer correctly aligned use std::aligned_storage, look in here for example:
http://www.cplusplus.com/reference/type_traits/aligned_storage/
Say I have the following code in a C++ program:
Object a = Object(someParameters);
new (&a) Object(someOtherParameters);
My assumption is that it replaces the contents of a with Object(someOtherParameters), avoiding a possible operator= declared for Object. Is this correct?
It's called placement new. It calles the constructor on the specified memory rather than allocating new memory. Note that in this case you have to explicitly call the destructor of your object before freeing the allocated memory.
Clarification. Suppose you have allocated some raw memory
char * rawMemory = new char [sizeof (Object)];
and you want to construct an object on that memory. You call
new(rawMemory) Object(params);
Now, before freeing the memory
delete [] rawMemory;
you will have to call the derstuctor of Object explicitly
reinterpret_cast<Object*>(rawMemory)->~Object();
In your particular example, however, the potential problem is that you haven't properly destroyed the existing object before constructing a new one in its memory.
Bonus:
Ever wondered how standard std::vector can do without its contained objects being default-constructible? The reason is that on most, if not all, implementations allocator<T> does not store a T* p which would require T to be default-constructible in case of p = new T[N]. Instead it stores a char pointer - raw memory, and allocates p = new char[N*sizeof(T)]. When you push_back an object, it just calls the copy constructor with placement new on the appropriate address in that char array.
It's known as placement new: it constructs the new Object at the address given inside the parentheses. Placement new is usually used to create an object in raw memory. Constructing a new object on top of an existing one, as this code does, is a bad idea, because it doesn't call the destructor on the original object.
In the use of "placement new" it is suggested to call the constructor and destructor explicitly.
In this case will the objects initialized in the initializer section of a class also get properly constructed?
Same too with explicitly calling the destructor? Do the member objects get destroyed properly?
In the use of "placement new" it is
suggested to call the constructor and
destructor explicitly.
It's not correct to say that "you call constructor explicitly", as constructors don't have names ($12.1/1).
In this case will the objects
initialized in the initializer section
of a class also get properly
constructed?
Yes. Why do you doubt it? Placment new only means that the new operator will not allocate any memory, rather will use the memory which you pass in placement new, to construct the object. The object gets constructed in the memory which you pass.
Same too with explicitly calling the
destructor? Do the member objects get
destroyed properly?
Yes.
In the use of "placement new" it is suggested to call the constructor and destructor explicitly.
I don't think so. It will say that you need to call the destructor explicitly.
In this case will the objects initialized in the initializer section of a class also get properly constructed?
Apart from the supplying of the memory all other aspects of placement new are the same as normal new. So rather than dynamically allocating memory it just uses the supplied pointer.
Same too with explicitly calling the destructor?
You can (if you feel naught) call the destructor explicitly on any object. It will call the user defined (or compiler generated) class destructor as normal. The reason you need to explicitly do it for objects created via placement new is that you can call delete on these objects. This is because delete assumes the object was created in dynamically allocated memory and tries to re-cycle that memory after the destructor has been called.
Do the member objects get destroyed properly?
Yes.
If we think of new like this:
// not real code
template<class T> T* new(void* location = NULL) (ArgumentsForT)
{
// If you do not provide location (normal usage)
// then we allocate some memory for you.
if (location == NULL)
{ location = malloc(sizeof(T)); // Use of malloc() is just an example
}
((T*)location)->Constructor(ArgumentsForT);
return (T*)location;
}
So placement new will work just like normal new.
Looking at the call to delete
template<typename T> void delete(T* obj)
{
if (obj != NULL)
{
obj->~T();
free(obj);
}
}
The trouble here is that delete can not tell if the memory was allocated by new or if the memory was allocated by the user and passed into new (placement new). So it always calls free on the memory. If you used placement new then you may not have dynamically allocated the memory (or the memory is still being used for something else).
char x[sizeof(T)]; // don't do this (memory may not be aligned correctly).
T* obj = new (x) T();
delete obj; // FAIL. The memory was not dynamically allocated.
// Delete will try and re-claim this memory for re-yse
// Even if the memory is local.
// This is why on placement new you need to call the destructor
obj->~T();
As referenced in this site...
http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.10
But i did not find the reason, why we should explicitly call the desturctor?
You can think of it as a call to delete, but since you used placement new, you don't want to use delete, as that would attempt to free the memory. If you wanted it to be called automatically, you could use RAII:
// Could use a templated version, or find an existing impl somewhere:
void destroy_fred(Fred* f) {
f->~Fred();
}
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
boost::shared_ptr<Fred> f(new(p) Fred(), destroy_fred);
// ...
// No need for an explicit destructor, cleaned up even during an exception
}
Normally, newed objects are destructed when delete is called. delete is never called for placement new, so you have to figure out when to destruct the object yourself, and do so explicitly.
You can't call ordinary delete because that would attempt free the memory, which was not allocated with ordinary new, so you call the destructor directly and then handle the underlying memory allocation depending on the architecture you are using.
Normally, an object is created using new, and destroyed when you call delete on the object. However, because 'delete' will also try to free the underlying memory back to the heap, you should never call delete on an object which which was instantiated using placement new.
Nevertheless, (no matter how it was allocated) every object ought to be destroyed (because its destructor might do something important).
Therefore instead of the object's being destroyed using delete, you have to destroy the object yourself, and do so explicitly, by invoking its destructor as shown in the FAQ you cited.
The example from your link:
void someCode()
{
char memory[sizeof(Fred)];
void* p = memory;
Fred* f = new(p) Fred();
...
f->~Fred(); // Explicitly call the destructor for the placed object
}
"placement new" return the memory offset that we provide. Right after new the compiler adds a call to the ctor ("placement new" is a also a trick to explicity call a ctor).
"memory" is allocated in the stack so we can not delete it.
string *ps = new string("Hello ");
The new in the above statement is called new operator which do two things
Call operator new(allocates
necessary memory like malloc) and
Call constructor
on raw memory created by operator
new to initialize
delete ps;
Again delete corresponds to
Destruction of object and
Deallocation of memory(i.e, free)
In c++ user is not allowed to call constructor directly,Placement new is used when you have raw memory allocated by some means and wanted to initialize the bits with constructor.Because the memory allocation process did not happen through operator new, delete cannot deallocate the memory.
void someCode()
{
char memory[sizeof(Fred)];//memory allocated on stack
void* p = memory;
Fred* f = new(p) Fred();//placement new
...
f->~Fred(); // Explicitly call the destructor for the placed object
}