5

If I have the following

#include <vector>

class C
{
public:
    C()
    :
        m_d(new int)
    {
        *m_d = 2;
    }

    ~C()
    {
        delete m_d;
    }

    int* m_d;
};

int main()
{
    std::vector<char> data;

    data.resize(sizeof(C));

    C* newC = new(&data[0]) C;

    C* cAgain = reinterpret_cast<C*>(&data[0]);
    cAgain->~C();

    return 0;
}

What exactly happens? When the std::vector<char> is destroyed, has it freed the memory twice? If it hasn't, why hasn't it? If it has, how would you prevent it?

Yunus Temurlenk
  • 4,085
  • 4
  • 18
  • 39
NeomerArcana
  • 1,978
  • 3
  • 23
  • 50
  • 1
    C doesn't restpect rule of 3/5/0 (fortunately, no copy occurs). Your placement new might have alignment issue. I think [`std::launder`](https://en.cppreference.com/w/cpp/utility/launder) is needed for `cAgain`. Except that it should be OK. – Jarod42 May 26 '20 at 11:18
  • @Jarod42 The default allocator is aligned to `std::max_align_t` – Artyer May 26 '20 at 11:27
  • @Jared42 can you explain the need for `std::launder`? – NeomerArcana May 26 '20 at 21:37
  • @NeomerArcana: See [is-it-ok-to-discard-placement-new-return-value-when-initializing-objects](https://stackoverflow.com/questions/49568858/is-it-ok-to-discard-placement-new-return-value-when-initializing-objects). – Jarod42 May 27 '20 at 07:33

2 Answers2

2

std::vector<char> data; handles its own memory which contains char, unrelated to C.

C* newC = new(&data[0]) C; call constructor of C, (which allocates).

When newC leaves scope, destructor of C is NOT called. (newC is just a pointer, not a C)

cAgain->~C(); call destructor of C (good). As for newC, when scope ends, no (extra) destructor of C is called.

So assuming correct alignment, and aliasing between newC and cAgain correct, your code is OK without leaks.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

You have declared data as vector of char so the vector object works on data type of char not you class C so when it is destroyed no destructor will be called because char has no one.

so only one destructor is called ~C()

Ahmed Anter
  • 650
  • 4
  • 13