I have a C function that returns me a C style array. I would like wrap this into more C++ style code, so I don’t have to manage its lifetime manually. So, I defined my wrapper as such:
template <typename T>
class Wrapper {
public:
std::unique_ptr<T[]> data;
explicit Wrapper(T data[]) : data(data) {}
};
However, when using it as follows:
int main(int argc, char *argv[])
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8}; // simulate my C style function
Wrapper<int> wrapped(arr);
return 0;
}
I get
double free or corruption (out)
Aborted
As far as I understand, the only place where arr is destroyed, should be the destructor of std::unique_ptr, which is destroyed as soon as its parent Wrapper is destroyed. What am I missing here?
>Solution :
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
This variable has automatic storage duration. It will be destroyed at the end of the scope where it is declared.
You pass a pointer to the first element of the automatic array into the constructor. The constructor initialises the unique pointer member to point to the automatic array. In the destructor, the unique pointer is destroyed and its destructor invokes delete[] on the stored pointer. Invoking delete[] on any pointer that was not acquired through new of an array results in undefined behaviour. The pointer in this case points to an automatic array which was not acquired by new[], and therefore the behaviour of the program is undefined.
As far as I understand, the only place where arr is destroyed, should be the destructor of std::unique_ptr
That is not where arr may be destroyed, because arr is an automatic variable.
In conclusion: (Almost) never store pointers to any variables in smart pointers. Only store pointers to dynamic objects, whose deallocation function matches the deleter of the smart pointer. Prefer to create smart pointers using std::make_unique (and related functions) when possible to avoid making this mistake in the future.