- sorry that I let you down yesterday
- as an excuse, I have fixed and commented your code. (remember to compile it with
-std=c++20
)
-std=c++20
)If you develop or debug a container, it is useful to have a special test class for the elements that covers potential container specific errors.
struct ContainerTester {
static int instances;
int counter{};
int val;
ContainerTester() : ContainerTester(0) {}
ContainerTester(int val) : val(val)
{
++counter;
++instances;
}
~ContainerTester() {
--counter;
--instances;
if (counter < 0) std::cout << "multiple destructor calls on same element" << std::endl;
if (instances < 0) std::cout << "negative number of instances" << std::endl;
}
};
int ContainerTester::instances{};
std::ostream& operator<<(std::ostream& o, const ContainerTester& c) {return o << c.val;}
If I run your code with ContainerTester
instead of int
, i get:
negative number of instances
negative number of instances
negative number of instances
negative number of instances
negative number of instances
negative number of instances
multiple destructor calls on same element
negative number of instances
double free or corruption (out)
segmentation fault
So it’s more obvious that very bad things do happen :)
Oh and note, that allocator::destroy
is deprecated in C++17 and was removed with C++20.
That’s btw. another error. You byte-copy the elements and Call the destructor on the original ones. This will work only, if your element’s type is trivially destructible.
Given your T has an allocating constructor and therefore an deallocating destructor:
Creating a T Calls T::T()
that allocates memory.
Resizing your deque Calls T::~T()
by .destroy()
, deallocating this memory.
Destructing your deque should destroy the elements. Thus you call the constructor once and the destructor 1+number of deque resizes.
I see. Let me know if my hint doesn’t take you further, then i take a closer look. It seems, that .destroy deallocates anyway and the later .deallocate deallocates the already deallocated memory again.
Double free corruption means you deallocate some memory twice.
Let me add a question: do you really want to implement your own deque? Because there already exists one in the STL.
Direct initialization is recommended over copy initialization (=).
Okay, to be fair: it’s some sort of holy war, the answer depends on who you ask.