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
}
Related
I found the following code while reading placement new operator.
#include <iostream>
using namespace std;
class MyClass {
public:
// Placement new operator
void* operator new (size_t sz, void* v) {
cout << "Placement new invoked" << endl;
return v;
}
~MyClass() {
// Cleanup
}
};
int main()
{
// Create a buffer to store the object
int buffer[16];
cout << "Starting address of my buffer = " << &buffer << endl;
// Create the object. Use placement new
MyClass* obj = new (buffer) MyClass();
cout << "Location of my object = " << obj << endl;
// Don't delete object created with placement delete
// Call the destructor explicitly
obj->~MyClass();
}
I have few questions related to delete object which was created using placement new:
what is the clean up code needs to write in destructor in order to
free memory which was occupied obj in buffer memory.
is it not needed to define placement delete, if yes whether it needs to be inside destructor or outside destructor. If it is outside destructor how it will be called ?
Regular new does two things:
allocate memory for your object
construct your object in that memory space.
Placement new means you manage one of those and the other is managed as before.
You allocate / provide the memory for your object
Constructor is called in that memory space.
The reverse is delete of which the regular delete does the following:
Invoke the destructor of the object to clean-up
Free the memory that was allocated for it.
Note that they are done in reverse order for obvious reasons. You cannot free the memory that contains information about what needs to be cleaned up, unti you have finished using that memory. Whereas in construction you need to get hold of the memory first.
In what you call placement delete but is really the reverse of placement new, you need to perform the first step of destruction but not the second. Thus you call the object's destructor, and then you can free up the memory it uses / use it for something else.
The most common example of usage of placement new is in the implementation of std::vector which requires a contiguous buffer for its data, and which lets you reserve ahead (and if you don't it will probably do it for you). That part allocates the memory but does not construct the objects in it. Thus when they are constructed later, placement new is used.
what is the clean up code needs to write in destructor in order to free memory which was occupied obj in buffer memory
The destructor should just do what any destructor does: clean up any resources managed by the object. In this case, it doesn't manage any resources, so there's no need to do anything.
It shouldn't do anything special according to how the storage for the object itself was allocated. Managing that storage is the job for custom new and delete operators, when required.
is it not needed to define placement delete
No. Placement-new is used to construct an object in storage that you're managing yourself, and it's your responsibility to free that storage yourself. In this case, the storage is automatic, so it's automatically freed when the function exits.
Just as the allocator for placement-new does nothing (just returning the provided pointer to pre-allocated storage), so the corresponding deallocator would do nothing; and so it doesn't exist. You just need to destroy the object by calling its destructor directly, before disposing of the storage yourself.
The first thing to ask is: what are you trying to do? If you
define a placement operator new in a class, then that is the
only operator new which will be found when you write new
MyClass; you must always specify the extra arguments. And in
almost every case where you define a class specific operator
new, you should also define a class specific operator delete;
otherwise the global operator delete function will be called
when you write delete p, and that generally won't work.
If your goal is to systematically require separation of
allocation and initialization, and that is why you are defining
a member operator new, then you can provide a no-op operator
delete; if the constructor of the class can throw, then you'll
also want to provide a placement operator delete, since this is
what will be called if the constructor of a newed object exits
via an exception. There is no other way to call it, however.
When providing placement operator new, you must provide
a default operator delete which does the right thing; and when
providing several operator new for the same type, you need to
memorize somehow in each allocation which one was called, in
order to dispatch in the non-placement operator delete.
And by the way, just allocating a buffer as a local variable
does not guarantee sufficient alignment for anything but the
declared buffer type.
EDIT:
Just an example of what would be needed for the operator
delete functions (which must be members):
void operator delete( void* p ) {}
void operator delete( void* p, void* ) {}
I'm new to the concept so don't be hard on me.
why doesn't this code produce a destructor call ?
The names of the classes are self-explanatory.
The SString will print a message in ~SString().
It only prints one destructor message.
int main(int argc, TCHAR* argv[])
{
smart_ptr<SString> smt(new SString("not lost"));
new smart_ptr<SString>(new SString("but lost"));
return 0;
}
Is this a memory leak?
The impl. for smart_ptr is from here
edited:
//copy ctor
smart_ptr(const smart_ptr<T>& ptrCopy)
{
m_AutoPtr = new T(ptrCopy.get());
}
//overloading = operator
smart_ptr<T>& operator=(smart_ptr<T>& ptrCopy)
{
if(m_AutoPtr)
delete m_AutoPtr;
m_AutoPtr = new T(*ptrCopy.get());
return *this;
}
By new smart_ptr<SString>(new SString("but lost")); you are creating a new, dynamically allocated smart pointer. You don't store the result of the allocation (a pointer to a shared_ptr to a SString) anywhere, it's dangling... since you don't store the result, you also can not call delete for it - therefore it's destructor won't be called, and in turn also the SString destructor of the contained object won't be called!
If you try
smart_ptr<SString> *p = new smart_ptr<SString>(new SString("but lost"));
delete p;
instead, you will see the destructor called also for this case.
However, that's no sensible use of a smart_ptr. smart_ptr were created so that you don't need to call delete manually; therefore, don't use them that way; use them as in your first statement!
The point of a smart pointer is that you're supposed to have only automatic smart pointer objects:
{
smart_ptr<Foo> p(new Foo);
}
// bye bye Foo
Your second line, however, creates a dynamic smart pointer, whose life never ends! Thus it never gets a chance to destroy the object it's in charge of.
You would have to delete the smart pointer itself manually, so that it can in turn clean up the object:
auto sp = new smart_ptr<Foo>(new Foo);
// ^^^^^^^
// ^^^^^^^^^^^^^^ +------< dynamic Foo, handled by the SP
// |
// +---------------< dynamic smart pointer, handled by YOU
delete sp;
Yes, the smart point itself is leaked. (And anything it holds a reference to).
I cannot think of a good reason to new a smart pointer...
Yes, it is a memory leak, you're leaking the second smart pointer and its contents.
The reason is that the first smart pointer is created on the stack, so its life-time is scoped to the block it is declared in, after that it will be automatically destroyed.
The second one is created on the heap, which means it will live until you destroy it with delete at which point its destructor will be called (and with that the destructor of the SString it is holding).
Assume you have an object of class Fool.
class Fool
{
int a,b,c;
double* array ;
//...
~Fool()
{
// destroys the array..
delete[] array ;
}
};
Fool *fool = new Fool() ;
Now, I know you shouldn't, but some fool calls the destructor on fool anyway. fool->~Fool();.
Does that mean fool's memory is freed, (ie a,b,c are invalid) or does that mean only whatever deallocations in ~Fool() function occur (ie the array is deleted only?)
So I guess my question is, is a destructor just another function that gets called when delete is called on an object, or does it do more?
If you write
fool->~Fool();
You end the object's lifetime, which invokes the destructor and reclaims the inner array array. The memory holding the object is not freed, however, which means that if you want to bring the object back to life using placement new:
new (fool) Fool;
you can do so.
According to the spec, reading or writing the values of the fields of fool after you explicitly invoke the destructor results in undefined behavior because the object's lifetime has ended, but the memory holding the object should still be allocated and you will need to free it by invoking operator delete:
fool->~Fool();
operator delete(fool);
The reason to use operator delete instead of just writing
delete fool;
is that the latter has undefined behavior, because fool's lifetime has already ended. Using the raw deallocation routine operator delete ensures that the memory is reclaimed without trying to do anything to end the object's lifetime.
Of course, if the memory for the object didn't come from new (perhaps it's stack-allocated, or perhaps you're using a custom allocator), then you shouldn't use operator delete to free it. If you did, you'd end up with undefined behavior (again!). This seems to be a recurring theme in this question. :-)
Hope this helps!
The destructor call does just that, it calls the destructor. Nothing more and nothing less. Allocation is separate from construction, and deallocation from destruction.
The typical sequence is this:
1. Allocate memory
2. Construct object
3. Destroy object (assuming no exception during construction)
4. Deallocate memory
In fact, if you run this manually, you will have to call the destructor yourself:
void * addr = ::operator new(sizeof(Fool));
Fool * fp = new (addr) Fool;
fp->~Fool();
::operator delete(addr);
The automatic way of writing this is of course Fool * fp = new Fool; delete fp;. The new expression invokes allocation and construction for you, and the delete expression calls the destructor and deallocates the memory.
Does that mean fool's memory is freed, (ie a,b,c are invalid) or does
that mean only whatever deallocations in ~Fool() function occur (ie
the array is deleted only?)
Fool::~Fool() has zero knowledge about whether the Fool instance is stored in dynamic storage (via new) or whether it is stored in automatic storage (i.e. stack objects). Since the object ceases to exist after the destructor is run, you can't assume that a, b, c and array will stay valid after the destructor exits.
However, because Fool::~Fool() knows nothing about how the Fool was allocated, calling the destructor directly on a new-allocated Fool will not free the underlying memory that backs the object.
You should not access a, b, and c after the destructor is called, even if it's an explicit destructor call. You never know what your compiler puts in your destructor that might make those values invalid.
However, the memory is not actually freed in the case of an explicit destructor call. This is by design; it allows an object constructed using placement new to be cleaned up.
Example:
char buf[sizeof (Fool)];
Fool* fool = new (buf) Fool; // fool points to buf
// ...
fool->~Fool();
The easiest place to see that the destructor is distinct from deallocation via delete is when the allocation is automatic in the first place:
{
Fool fool;
// ~Fool called on exit from block; nary a sign of new or delete
}
Note also the STL containers make full use of the explicit destructor call. For example, a std::vector<> treats storage and contained objects lifetime quite separately.
Can we call delete on the pointer which is allocated with the placement new? If no then why? Please explain in details.
I know that there is no placement delete. But I wonder why just delete opetator can not delete the memory without caring how that memory on which the pointer points is allocated?
delete is doing two things:
Calls destrucor
Frees memory
And I see no reaason for delete not to be able to call either of these two operations on the object which was created by placement new. Any idea about reasons?
You must only call delete on pointers that were created with operator new. If you use placement new with a memory location that was allocated by the normal operator new then you may safely use delete on it (provided you get the types and pointers right). However, you can use placement new on any memory, so you usually will manage that memory some other way and call the object's destructor manually.
For instance, in this convoluted and usually unnecessary scenario, it is safe to delete the memory you used placement new on, but only because you allocated it with new before:
char* mem = new char[sizeof(MyObject)];
MyObject* o = new (mem) MyObject;
// use o
o->~MyObject(); // with placement new you have to call the destructor by yourself
delete[] mem;
However, this is illegal:
char mem[16]; // create a buffer on the stack, assume sizeof(MyObject) == 16
MyObject* o = new (mem) MyObject; // use stack memory to hold a MyObject
// note that after placement new is done, o == mem
// pretend for this example that the point brought up by Martin in the comments didn't matter
delete o; // you just deleted memory in the stack! This is very bad
Another way to think of it is that delete only deallocates memory allocated previously by the normal new. With placement new, you do not have to use memory that was allocated by the normal new, so with the possibility of not having been allocated by normal new, delete cannot deal with it.
EDIT1: I know that there is no placement delete. But I wonder why just
delete opetator can not delete the memory without caring how that
memory on which the pointer points is allocated?
Because each flavour of memory allocation uses some implementation specific tracking of the memory (usually a header block that precedes the user address) and this make the allocation/deallocation to work only when paired up correctly:
new must pair with delete
new[] must pair with delete[] (most implementations though forgive mixing the newand new[])
malloc and frieds must pair with free
CoTaskMemAlloc pairs with CoTaskMemFree
alloca pairs with nothing (stack unwinding takes care of it)
MyCustomAllocator pairs with MyCustomFree
Attempting to call the wrong deallocator will result in unpredictable behavior( most likely seg fault now or later). Therefore calling delete on memory allocated by anything else other than new will result in bad things.
Furthermore the placement new may be called on any address, may not even be an allocated address. It can be called on an address located in the middle of some larger object, it may be called on a memory mapped region, it may be called on a raw virtual committed region, anything goes. delete woul attempt, in all these cases, to do what its implementation tell him to do: subtract the header size, interpret it as a new header, link it back into the heap. Kaboom.
The one that know how to release the memory of a placement new address is you, since you know exactly how was that memory allocated. delete will only do what it knows, and it may not be the right thing.
No, since delete not only calls the destructor but also frees the memory, but if you used placement new you must have allocated the memory yourself using malloc() or stack. You do, however, have to call the destructor yourself. Also see the C++ FAQ.
No. There is no placement-delete expression.
Typical scenario:
void * const addr = ::operator new(sizeof(T)); // get some memory
try {
T * const pT = new (addr) T(args...); // construct
/* ... */
p->~T(); // nap time
}
catch (...) {
}
::operator delete(addr); // deallocate
// this is _operator_-delete, not a delete _expression_
Note that the placement-new operator does have a corresponding delete operator which is mandated to be precisely void ::operator delete(void* [, size_t]) { }, a no-op; this is what gets called if the constructor of T throws an exception.
No, because a placement new doesn't allocate any memory. You use placement new on previously allocated raw memory. The only thing it does is call the constructor of the 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();