You are experiencing a double deletion bug. Consider this simple example:
struct Other {};
struct MyObj {
Other *p;
MyObj () : p(new Other) {}
~MyObj () { delete p; }
};
std::vector<MyObj> data;
data.push_back(MyObj());
The temporary object that is pushed onto data
is stored properly. However, since it is a temporary, it is destroyed right after the push. This means, the p
member is deleted when the temporary is destroyed, so the vector's version of the copy has a dangling pointer. When the vector object is destroyed, the pointer will be deleted again, resulting in a corrupted heap. The error message you received was from the glibc
code complaining about the resulting bad state.
To fix this problem, a proper copy constructor should be defined, to pass ownership of the objects from the temporary to the destination. The rule of three says we should define the assignment operator as well.
struct MyObj {
mutable Other *p;
MyObj () : p(new Other) {}
MyObj (const MyObj &o) : p(o.p) { o.p = 0; }
~MyObj () { delete p; }
const MyObj & operator = (MyObj o) {
using namespace std;
swap(*this, o);
return *this;
}
};
The use of mutable is required to be able to modify the p
member when the instance is const
, and const
was needed because temporaries are being passed in to the copy constructor. With this change, pushing items into the vector work fine.
A better solution would be to define p
to use a unique_ptr
instead.
struct MyObj {
std::unique_ptr<Other> p;
MyObj () : p(new Other) {}
};
No destructor is needed in this example, since the default destructor will destruct p, which will cause the Other
instance to be deleted by unique_ptr
.