lundi 25 avril 2016

Does this cause UD or a memory leak?

We have a simple class, which allocates memory for a pointer using placement new and then constructs values in place. All good (I hope).

The point of interest is the move constructor. When I swap the pointers between the two objects (let's call them A and B, A is constructed from B), the pointer in A is now the owning pointer and the pointer in B is not an owning pointer. So then the destructor in A will deal with the clean up, but the destructor in B will choke because it will try to delete a non owning pointer (not allocated with new). I fixed that by adding an if statement to check if the size is zero (indicating not yet created object).

Yet when I compile and run this, the console just freezes. I can't seem to find the problem.

#include <iostream>
#include <cstddef>
#include <utility>

using std::size_t;

template<typename T>
class foo
{
private:
    T* p = nullptr;
    size_t sz = 0;

public:
    foo(T* first, T* last)
        : p(nullptr), sz(static_cast<size_t>(last - first))
    {
        p = static_cast<T*>(::operator new(sz * sizeof(T)));

        for (size_t i = 0; first != last; ++first, ++i) {
            ::new(static_cast<void*>(&p[i])) T(*first);
        }
    }

    foo(foo&& rhs) noexcept
    {
        std::swap(p, rhs.p);
        std::swap(sz, rhs.sz);
    }

    ~foo()
    {
        if (sz != 0)
        {
            for (size_t i = 0; i < sz; ++i) {
                (&p[i])->~T();
            }
            ::operator delete(static_cast<void*>(p));
        }
    }
};

int main()
{
    int arr[5] = { 1, 2, 3, 4, 5 };
    foo<int> f(arr, arr + 5);
    foo<int> f2 = std::move(f);
}

Aucun commentaire:

Enregistrer un commentaire