0
Foo* foo1 = static_cast<Foo*>( alloca( sizeof( Foo ) * numTargets ) );
new (foo1) Foo();   // Statement 1:  Calls constructor Foo()

Foo** foo2 = static_cast<Foo**>( alloca( sizeof( Foo* ) * numTargets ) );
new (foo2) Foo*();   // Statement 2: Doesn't calls constructor Foo()

In my current project, statements 1 & 2 are not present.

Not having statement#1 leads to crash (a bug) when an attempt is made to populate value in foo1[i]. I fixed it by introducing statement#1. But I am not sure about few things :

  1. Should I use new (foo1) Foo[numTargets ]; instead of new (foo1) Foo();
  2. Should I introduce statement#2 for safegaurding against any future bug? What impact does statement#2 have in actuality?
  3. How does the statement#1 help to prevent the crash?
  4. Is there any Memory leak in either of the cases? Do we have to call the destructor explicitly for both cases?
Saurav Sahu
  • 13,038
  • 6
  • 64
  • 79

1 Answers1

2

Should I use new (foo1) Foo[numTargets ]; instead of new (foo1) Foo();

No. Array placement-new requires additional memory in the allocation to store details about the array. The C++ standard states that the amount of additional memory is unspecified, meaning it's up to the C++ compiler and/or standard library implementation.

You should instead loop through your array and placement-new each object:

for (size_t i = 0; i < numTargets; ++i) {
    new (foo1 + i) Foo();
}

Should I introduce statement#2 for safegaurding against any future bug? What impact does statement#2 have in actuality?

All this does is set foo2[0] to be equal to nullptr.

How does the statement#1 help to prevent the crash?

It is undefined behavior to use an object that has not been constructed. A crash is one possible outcome, but dereferencing foo1 in any way before the pointed-to object has been constructed can result in any behavior.

Is there any Memory leak in either of the cases? Do we have to call the destructor explicitly for both cases?

There is no memory leak inherent in the second, except that you effectively have an array of pointers. If you assigned any element in this array and don't delete that element then you could leak an allocation (depending on whether this array owns the allocations).

You must explicitly call destructors in the first case, which should prevent any memory leaks from whatever memory Foo objects might dynamically allocate.

for (size_t i = 0; i < numTargets; ++i) {
    foo1[i].~Foo();
}

Honestly, you would be much better off just using an std::vector here.

cdhowie
  • 158,093
  • 24
  • 286
  • 300