Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it dangerous to use placement new on an old object without explicitly calling the destructor first?

I would like to recycle memory for an object rather than deallocating and reconstructing it. Is the following usage of "placement new" safe, assuming that Foo in practice does not contain pointers (but might contain functions)?

Also, is the final delete call safe, and will it correctly call the destructor on the second "new" object, and correctly free the memory afterwards?

#include <new>
struct Foo {
    int hello;
    int world;
};

int main() {
    Foo* foo = new Foo;
    // Do something with foo
    // Done with foo, writing a new version of foo on top of the old one.
    new(foo) Foo();

    delete(foo);
}

The simple example above compiles and runs without errors, but I cannot tell by running it whether it might blow up for some reason in a more complex environment.

like image 550
merlin2011 Avatar asked Dec 12 '13 11:12

merlin2011


People also ask

Does placement new call destructor?

An explicit call to destructor is only necessary when an object is placed at a particular location in memory by using placement new. Destructor should not be called explicitly when the object is dynamically allocated because the delete operator automatically calls destructor.

When to use placement new?

Placement new is used when you do not want operator new to allocate memory (you have pre-allocated it and you want to place the object there), but you do want the object to be constructed.

What happens when destructor is not called?

There are two reasons that your destructors aren't being called, one is as kishor8dm pointed out that you are using the operator "new" and because of that the "delete" command must be called explicitly.

Does C++ automatically call destructors?

A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to delete .


1 Answers

It's safe because the object you're overwriting has a trivial destructor. From n3337, chapter 3.8 (Object lifetime):

4 A program may end the lifetime of any object by reusing the storage which the object occupies or by explicitly calling the destructor for an object of a class type with a non-trivial destructor. For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression (5.3.5) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.

The delete call is safe, too. You're calling it on a pointer that you got from new and there's a live object at that place.

And as you hinted in the question, it could invoke undefined behaviour if the destructor is non-trivial and has side effects - you need to call it explicitly in that case. Whether or not the class contains pointers is not directly important - reusing the storage is safe even in that case, but of course, you could introduce memory leaks and other bugs that way.

like image 52
jrok Avatar answered Sep 28 '22 16:09

jrok