1

I am trying to understand how unique pointers and move semantics. Now, I have created a dummy example below to show what the issue is. My question is, why does this code throw a pointer being freed was not allocated error?:

#include <iostream>
#include <memory>

using namespace std;

template <class T>
class Object
{
public:
    T *values = nullptr;
    int size;
    Object(int size) : size(size)
    {
        values = new T[size];
    }

    ~Object()
    {
        delete[] this->values;
    }

    void myFunc(T *&&new_values)
    {
        cout << "myFunc called!" << endl;
        delete[] this->values;
        values = new_values;
    }

    void print()
    {
        for (int i = 0; i < size; i++)
            cout << this->values[i] << " ";
        cout << endl;
    }
};

int main()
{
    auto my_object = new Object<int>(4);
    std::unique_ptr<Object<int>> my_other_object(new Object<int>(4));

    int values[4] = {1, 2, 3, 4};
    int my_other_values[4] = {10, 20, 30, 40};

    /* This works all fine! */
    my_object->myFunc(std::move(values));
    my_object->print();

    /* This next bit throws pointer being freed was not allocated */
    my_other_object->myFunc(std::move(my_other_values));
    my_other_object->print();
}
finite_diffidence
  • 893
  • 2
  • 11
  • 20
  • You cannot move in an array allocated on the stack into your 'unique ptr' because delete[] ing that array is UB it was never newed. This is effectively like doing: `int x = 4; { auto p = std::unique_ptr(&x); }` which isn't legal either. – Borgleader Sep 12 '20 at 13:08
  • Ah that makes so much sense now. Thank you sir! – finite_diffidence Sep 12 '20 at 13:10

1 Answers1

4

This has nothing to do with std::unique_ptr. The reason you get the "pointer being freed was not allocated" error is because the shown code is trying to delete something that was not newed.

    delete[] this->values;
    values = new_values;

This properly deletes the old values, but then just blindly sets values to point to something that was never newed (the new_values that get passed into here are not newed anywhere).

Hence, later, this object's destructor attempts to delete what's now in values, but it was never newed (it just points to some static array) and you get the runtime error.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148