Is it OK not to call the destructor on placement new allocated objects?

Lorah Attkins

Say I have a fixed memory buffer

char *buffer; 

And I allocate my structures in that buffer using placement new

struct S
{ 
    std::tuple<int, double, char> m_data; 
    auto getRecord() 
    { 
        return m_data;
    }
};

S *newS = new(buffer + offset)S; 

I know that I'm supposed to manually call the destructor of such allocated items but if there's no bookeeping / resource management involved is it ok to omit this? In other words if the destructor of the classes using the buffer is not doing anything (similar to ~S() above) is it ok to skip this step? If that's the case can I reuse the buffer without destroying the previous tenants?

Ben Voigt

The standard has a rule in section 3.8 [basic.life] that covers this:

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.

Lots of experts are in agreement that "depends on the side effects produced by the destructor" is far too vague to be useful. Many interpret it as a tautology meaning "If the program has undefined behavior when the destructor side effects are not evaluated, then failing to call the destructor causes undefined behavior". See Observable behavior and undefined behavior -- What happens if I don't call a destructor?

If your type has a trivial destructor (which appears to be the case in your example), then calling it (or failing to call it) has no effect whatsoever -- calling a trivial destructor does not even end the life of the object.

The lifetime of an object o of type T ends when:

  • if T is a class type with a non-trivial destructor, the destructor call starts, or
  • the storage which the object occupies is released, or is reused by an object that is not nested within o.

That is, if T doesn't have a non-trivial destructor, the only way to end the lifetime of object o is to release or reuse its storage.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Is it safe to call placement new on `this` for trivial object?

Is it OK to make a placement new on memory managed by a smart pointer?

Swapping storage buffers containing placement new created objects

Finding out the largest size of several objects for placement new

is it ok to clear vector in a destructor

Will `params` in C# always cause a new array to be allocated on every call?

are objects allocated without using "new" allocated on stack or heap

How To Destruct Destructor-less Types Constructed via 'Placement New'

Is it allowed to call destructor explicitly followed by placement new on a variable with fixed lifetime?

Placement new and destructor

Destructor called implicitly every time I allocate with placement new

Destroy call in placement new

Is it OK to discard placement new return value when initializing objects

Constexpr alternative to placement new to be able to leave objects in memory uninitialized?

Placement new for non-copyable objects

destructor on placement-new

should the destructor be called with placement new even on the same type

how to call destructor on some of the objects in a Dynamic Array

Initializing objects with virtual functions on pre-allocated memory without placement new operator - is that possible? If not, why

Placement new, objects placed over I/O registers and zeroed memory

how do you delete an object allocated with placement new

Is it ok to "delete" memory allocated with "new[1]" and vice-versa?

What happens if you call a destructor and use the allocated memory again for other objects?

C++ placement new, inheritance and destructor

How to affect memory allocated by new and casted to an array od class objects?

Pointer being freed was not allocated - destructor

What happens to members of a stack-allocated class put down with placement new on scope end?

Does placement-new into the same type still require to manually call the destructor?

If std::vector reallocates objects to new memory by using move constructor then why does it have to call the destructor on the original objects?