This line is problematic:
output = Container(input);
You didn't declare a copy assignment operator so you get the default one which is member to member assignment. data
pointer will then be duplicated. Since you are using a local object that goes out of scope at the end of the function, data
is deleted. Later, when output is destructed, you hit the double delete problem. That is why by introducing a dynamic allocation and not releasing it, it "fixes" the problem.
You should declare a copy assignment operator to also copy data content like in your copy constructor.
You are missing one part of the rule of three. When you need to declare a copy constructor and destructor, you also need a copy assignment operator.
You also have a leak in your copy constructor, you should delete data before re-allocating it.
EDIT after your comment
You have a leak in copy constructor because in your other constructor, you allocate an array of 1 element. In the copy constructor, you allocate for the other size without first deleting the previously allocated data array.
For declaring a copy assignment operator you normally return a reference like so:
CMatrix& CMatrix::operator=(const CMatrix& mat)
but you don't theoretically need to allocate a new object. Although the allocate and swap is a common implementation pattern.