Reputation: 117
I have the following class design:
struct compare{
template <typename T>
bool operator()(const T& a, const T&b){ return *a < *b;}
};
class Trans;
typedef set<shared_ptr<Trans>, compare > TransPointerSet;
class Place{
// other data members
TransPointerSet nextTrans;
public:
// constructor and other methods including overloaded < operator
void insertNextTrans(shared_ptr<Trans> t){ nextTrans.insert(t); }
void removeNextTrans() { nextTrans.clear(); }
};
typedef set<shared_ptr<Place>, compare > PlacePointerSet;
class Trans{
//other data members
PlacePointerSet inPlaces;
PlacePointerSet outPlaces;
public:
//constructor and others including overloaded < operator
void insertInPlace(shared_ptr<Place> p){
inPlaces.insert(p);
p->insertNextTrans(shared_ptr<Trans>(this)); }
void insertOutPlace(shared_ptr<Place> p){ //body }
void print() cosnt { //body }
};
class Net{
TransPointerSet acts;
//other data members
public:
//constructor and others
};
And here is my main for testing whether the classes are properly working or not.
int main()
{
shared_ptr<Place> p1 = make_shared<Place>();
shared_ptr<Place> p2 = make_shared<Place>();
shared_ptr<Trans> t = make_shared<Trans>();
t->insertInPlace(p1);
t->insertOutPlace(p2);
t->print();
}
The problem is after successful compilation it ends up with "double free or corruption (fasttop) error" after t->print() properly working. I realize the bug lies in the circular dependency created by firstly taking p1 as member of t->inPlaces which inserts t as member of p1. But I need this both way linking. Also, I tried to reset every member of nextTrans in class Place by a method after t->print(), but that didn't work because the pointers are in a set. So can anyone suggest any way to fix this problem?
Upvotes: 1
Views: 2031
Reputation: 340188
This line in Trans::insertInPlace()
:
p->insertNextTrans(shared_ptr<Trans>(this));
creates a separate, unrelated shared pointer to the same object. You need to use std::enable_shared_from_this
for the Trans
class:
class Trans: public std::enable_shared_from_this {
// ....
};
Then in Trans::insertInPlace()
:
p->insertNextTrans(shared_from_this());
Upvotes: 5
Reputation: 409166
It's because you can't make a shared pointer from this
just like that. By doing it you now have two shared pointers to the Trans
instance, both pointing to the same instance but with their separate reference counters. That means that both will try to delete
the pointer.
You need to use std::enable_shared_from_this
. The linked reference page have a very good example of your problem.
Upvotes: 6