Borph
Borph

Reputation: 933

Is double-construction undefined behaviour?

In our codebase, a pool of memory chunks is used and upon 'allocation' the object gets constructed using a "placement new". I'm missing the destructor call though, finding it odd to allow "double construction", and wonder if it is undefined behaviour to call the constructor another time on the same object.

In C++11 3.8.4 [basic.life] it reads

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.

Does this mean that missing out the destructor call is actually ok, as long as we talk about types which have destructors without side-effects?

Edit: Context is: embedded SW without heap, own container implementations doing placement-new on c-array-elements or byte-arrays.

Upvotes: 4

Views: 156

Answers (2)

darune
darune

Reputation: 10962

This answer already answers the question well.

Although, I would add that using placement new in production code is usually a bad practice, error prone and/or a mistake. Many excellent alternatives exist (including some libraries). So you should look to simpler alternatives (could be as simpel as using a std::vector instead - calling reserve() if absolutely needed!) - also sometimes the use and introduction of placement new in codebase in the first place is oftentime misguided, legacy or sometimes a case of premature optimization.

Albeit it's hard to give concrete advice - one method could be just remove placement new or replace it with some kind of standard container - and then check if any problems arises (usually performance).

In my experience just removing the use of placement new in legacy code leads to no issues since the performance problem that it (maybe) used to fix has become largely obsolete by a wide range of 'system' optimizations (from the c++ level down to the hardward level).

Upvotes: 1

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275350

You can double construct without UB. The new object is a completely different one, and following pointers/references to the old one is UB.

It is really easy to trip over UB when doing placement new, let alone when double constructing.

Not calling a destructor just means the object is not cleaned up. If the destructor is trivial, this is not going to have much risk. Constructing an object over another object end an objects lifetime, as does calling the destructor.

If the object is in automatic storage with the proper type, constructing a different object over it and exiting the scope (causing the no longer existing original object to be destroyed) is usually UB (you can avoid UB here with a trivial destructor of the original object; this is why byte-buffers can have placement new done in them).

Upvotes: 2

Related Questions