2014-01-29 2 views
1

У меня есть следующий класс дизайн:Двойной ошибка удаления с shared_ptr C++

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 
}; 

А вот мое главное для тестирования ли классы работают должным образом или нет.

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(); 
} 

Проблема после успешной компиляции он заканчивает с «двойной свободной или коррупции (fasttop) ошибка» после t-> печати() работает нормально. Я понимаю, что ошибка лежит в круговой зависимости, созданной, сначала принимая p1 как член t-> inPlaces, который вставляет t в качестве члена p1. Но мне нужно это в обоих направлениях. Кроме того, я попытался сбросить каждый член nextTrans в классе Place методом после t-> print(), но это не сработало, потому что указатели находятся в наборе. Так может ли кто-нибудь предложить любой способ исправить эту проблему?

ответ

6

Это потому, что вы не можете сделать общий указатель от this просто так. Делая это, вы теперь имеете два общих указателя на экземпляр Trans, оба указывающие на один и тот же экземпляр, но с их отдельными счетчиками ссылок. Это означает, что оба будут пытаться указывать указатель delete.

Вам необходимо использовать std::enable_shared_from_this. На ссылочной странице есть очень хороший пример вашей проблемы.

+0

Спасибо! это очень помогло! –

4

Эта линия в Trans::insertInPlace():

p->insertNextTrans(shared_ptr<Trans>(this)); 

создает отдельный, не связанный общий указатель на тот же объект. Вы должны использовать std::enable_shared_from_this для Trans класса:

class Trans: public std::enable_shared_from_this { 
    // .... 
}; 

Тогда в Trans::insertInPlace():

p->insertNextTrans(shared_from_this()); 
+0

Спасибо! это очень помогло! –

Смежные вопросы