cyclic dependency of shared ptr, not allowing destructor to invoke
by shamjs from LinuxQuestions.org on (#5MF9R)
In my code looks like I have a cyclic dependency of shared pointer as a result of it I believe destructor is not getting invoked.
Here is my code
Code:#include<stdio.h>
#include<iostream>
#include<memory>
#include<list>
using namespace std;
class IObserver {
public:
IObserver() {}
virtual ~IObserver();
virtual void Update(const std::string &message_from_subject) = 0;
virtual int GetObjectId() = 0;
};
class ISubject {
public:
ISubject() {}
virtual ~ISubject();
virtual void Attach(shared_ptr<IObserver> pObserver) = 0;
virtual void Detach(shared_ptr<IObserver> pObserver) = 0;
virtual void Notify() = 0;
};
class Subject : public ISubject {
public:
Subject() { cout<<"Subject constructor"<<endl; }
~Subject() {
std::cout << "Subject Destructor.\n";
}
void Attach(shared_ptr<IObserver> pObserver);
void Detach(shared_ptr<IObserver> pObserver);
void Notify();
void CreateMessage(std::string message);
private:
typedef shared_ptr<IObserver> PtrObserver;
std::list<PtrObserver> plist_observer;
std::string message;
};
class Observer : public IObserver {
public:
Observer(shared_ptr<Subject> pSubject);
~Observer() {
std::cout << "Observer Destructor Id " <<objId<<endl;
}
void Update(const std::string &message_from_subject);
void DeleteFromList();
int GetObjectId();
private:
std::string message_from_subject_;
shared_ptr<Subject> ptrSubject;
int objId;
static int objCount;
};
#include "ObserverPattern.hpp"
int Observer::objCount = 0;
IObserver::~IObserver() {
cout<<"Done with IObserver"<<endl;
}
ISubject::~ISubject() {
cout<<"Done with ISubject"<<endl;
}
/* Subject::Attach
* Description : Attach/subscribe the interested obersever
* param : pObserver
*/
void Subject::Attach(shared_ptr<IObserver> pObserver) {
cout<<"Subject::Attach attaching Object"<<pObserver->GetObjectId()<<endl;
plist_observer.push_back(pObserver);
}
/* Subject::Attach
* Description : Detach/unsubscribe the interested obersever
* param : pObserver
* */
void Subject::Detach(shared_ptr<IObserver> pObserver) {
cout<<"Subject::Detach detaching Object"<<pObserver->GetObjectId()<<endl;
plist_observer.remove(pObserver);
}
/* Subject::Notify
* Description : Notify the subscribed observers about the message
* */
void Subject::Notify() {
cout<<"Subject::Notify"<<endl;
std::list<PtrObserver>::iterator iterator = plist_observer.begin();
while (iterator != plist_observer.end()) {
(*iterator)->Update(message);
++iterator;
}
}
/* Subject::CreateMessage
* Description : Create a message and notify the same for all the interested observers
* */
void Subject::CreateMessage(std::string message) {
cout<<"######### Subject::CreateMessage ########## "<<message<<endl;
this->message = message;
Notify();
}
Observer::Observer(shared_ptr<Subject> pSubject) : ptrSubject(pSubject) {
objCount++;
objId = objCount;
cout<<" Constructing Object "<<objId<<endl;
ptrSubject->Attach(make_shared<Observer>(*this));
}
/* Observer::GetObjectId
* Description : Return the object Id associated with the object.
*/
int Observer::GetObjectId() {
return objId;
}
/* Observer::Update
* Description : Receives the updates from the subject
*/
void Observer::Update(const std::string &message_from_subject) {
message_from_subject_ = message_from_subject;
cout<<"Object Id "<<objId<<" Received "<<message_from_subject_<<" message"<<endl;
}
/* Observer::DeleteFromList
* Description :
* */
void Observer::DeleteFromList() {
shared_ptr<IObserver> observer(this);
ptrSubject->Detach((observer));
}
int main() {
shared_ptr<Subject> subject = make_shared<Subject>();
shared_ptr<Observer> observer1(make_shared<Observer>(subject));
shared_ptr<Observer> observer2(make_shared<Observer>(subject));
shared_ptr<Observer> observer3(make_shared<Observer>(subject));
subject->CreateMessage("Hi Hello");
//observer2->DeleteFromList(); // Double free or corruption error
subject->Detach(observer2); // does not detach observer2
shared_ptr<Observer> observer4(make_shared<Observer>(subject));
subject->CreateMessage("Welcome");
return 0;
}Here is the output
Code:Subject constructor
Constructing Object 1
Subject::Attach attaching Object1
Constructing Object 2
Subject::Attach attaching Object2
Constructing Object 3
Subject::Attach attaching Object3
######### Subject::CreateMessage ########## Hi Hello
Subject::Notify
Object Id 1 Received Hi Hello message
Object Id 2 Received Hi Hello message
Object Id 3 Received Hi Hello message
Subject::Detach detaching Object2
Constructing Object 4
Subject::Attach attaching Object4
######### Subject::CreateMessage ########## Welcome
Subject::Notify
Object Id 1 Received Welcome message
Object Id 2 Received Welcome message
Object Id 3 Received Welcome message
Object Id 4 Received Welcome message
Observer Destructor Id 4
Done with IObserver
Observer Destructor Id 3
Done with IObserver
Observer Destructor Id 2
Done with IObserver
Observer Destructor Id 1
Done with IObserverSubject class contains a list of IObserver shared pointers
Observer class has a shared pointer referring to Subject.
Issues
1. Destructor of Subject and ISubject class is not invoked
2. observer2->DeleteFromList(); // Double free or corruption error is noticed
3. subject->Detach(observer2); // is not detaching the observer2
I need inputs on
1. how to resolve this cyclic dependency error of the shared ptr
2. And why I am unable to detach observer2 from the list
Inputs will be appreciated.
Here is my code
Code:#include<stdio.h>
#include<iostream>
#include<memory>
#include<list>
using namespace std;
class IObserver {
public:
IObserver() {}
virtual ~IObserver();
virtual void Update(const std::string &message_from_subject) = 0;
virtual int GetObjectId() = 0;
};
class ISubject {
public:
ISubject() {}
virtual ~ISubject();
virtual void Attach(shared_ptr<IObserver> pObserver) = 0;
virtual void Detach(shared_ptr<IObserver> pObserver) = 0;
virtual void Notify() = 0;
};
class Subject : public ISubject {
public:
Subject() { cout<<"Subject constructor"<<endl; }
~Subject() {
std::cout << "Subject Destructor.\n";
}
void Attach(shared_ptr<IObserver> pObserver);
void Detach(shared_ptr<IObserver> pObserver);
void Notify();
void CreateMessage(std::string message);
private:
typedef shared_ptr<IObserver> PtrObserver;
std::list<PtrObserver> plist_observer;
std::string message;
};
class Observer : public IObserver {
public:
Observer(shared_ptr<Subject> pSubject);
~Observer() {
std::cout << "Observer Destructor Id " <<objId<<endl;
}
void Update(const std::string &message_from_subject);
void DeleteFromList();
int GetObjectId();
private:
std::string message_from_subject_;
shared_ptr<Subject> ptrSubject;
int objId;
static int objCount;
};
#include "ObserverPattern.hpp"
int Observer::objCount = 0;
IObserver::~IObserver() {
cout<<"Done with IObserver"<<endl;
}
ISubject::~ISubject() {
cout<<"Done with ISubject"<<endl;
}
/* Subject::Attach
* Description : Attach/subscribe the interested obersever
* param : pObserver
*/
void Subject::Attach(shared_ptr<IObserver> pObserver) {
cout<<"Subject::Attach attaching Object"<<pObserver->GetObjectId()<<endl;
plist_observer.push_back(pObserver);
}
/* Subject::Attach
* Description : Detach/unsubscribe the interested obersever
* param : pObserver
* */
void Subject::Detach(shared_ptr<IObserver> pObserver) {
cout<<"Subject::Detach detaching Object"<<pObserver->GetObjectId()<<endl;
plist_observer.remove(pObserver);
}
/* Subject::Notify
* Description : Notify the subscribed observers about the message
* */
void Subject::Notify() {
cout<<"Subject::Notify"<<endl;
std::list<PtrObserver>::iterator iterator = plist_observer.begin();
while (iterator != plist_observer.end()) {
(*iterator)->Update(message);
++iterator;
}
}
/* Subject::CreateMessage
* Description : Create a message and notify the same for all the interested observers
* */
void Subject::CreateMessage(std::string message) {
cout<<"######### Subject::CreateMessage ########## "<<message<<endl;
this->message = message;
Notify();
}
Observer::Observer(shared_ptr<Subject> pSubject) : ptrSubject(pSubject) {
objCount++;
objId = objCount;
cout<<" Constructing Object "<<objId<<endl;
ptrSubject->Attach(make_shared<Observer>(*this));
}
/* Observer::GetObjectId
* Description : Return the object Id associated with the object.
*/
int Observer::GetObjectId() {
return objId;
}
/* Observer::Update
* Description : Receives the updates from the subject
*/
void Observer::Update(const std::string &message_from_subject) {
message_from_subject_ = message_from_subject;
cout<<"Object Id "<<objId<<" Received "<<message_from_subject_<<" message"<<endl;
}
/* Observer::DeleteFromList
* Description :
* */
void Observer::DeleteFromList() {
shared_ptr<IObserver> observer(this);
ptrSubject->Detach((observer));
}
int main() {
shared_ptr<Subject> subject = make_shared<Subject>();
shared_ptr<Observer> observer1(make_shared<Observer>(subject));
shared_ptr<Observer> observer2(make_shared<Observer>(subject));
shared_ptr<Observer> observer3(make_shared<Observer>(subject));
subject->CreateMessage("Hi Hello");
//observer2->DeleteFromList(); // Double free or corruption error
subject->Detach(observer2); // does not detach observer2
shared_ptr<Observer> observer4(make_shared<Observer>(subject));
subject->CreateMessage("Welcome");
return 0;
}Here is the output
Code:Subject constructor
Constructing Object 1
Subject::Attach attaching Object1
Constructing Object 2
Subject::Attach attaching Object2
Constructing Object 3
Subject::Attach attaching Object3
######### Subject::CreateMessage ########## Hi Hello
Subject::Notify
Object Id 1 Received Hi Hello message
Object Id 2 Received Hi Hello message
Object Id 3 Received Hi Hello message
Subject::Detach detaching Object2
Constructing Object 4
Subject::Attach attaching Object4
######### Subject::CreateMessage ########## Welcome
Subject::Notify
Object Id 1 Received Welcome message
Object Id 2 Received Welcome message
Object Id 3 Received Welcome message
Object Id 4 Received Welcome message
Observer Destructor Id 4
Done with IObserver
Observer Destructor Id 3
Done with IObserver
Observer Destructor Id 2
Done with IObserver
Observer Destructor Id 1
Done with IObserverSubject class contains a list of IObserver shared pointers
Observer class has a shared pointer referring to Subject.
Issues
1. Destructor of Subject and ISubject class is not invoked
2. observer2->DeleteFromList(); // Double free or corruption error is noticed
3. subject->Detach(observer2); // is not detaching the observer2
I need inputs on
1. how to resolve this cyclic dependency error of the shared ptr
2. And why I am unable to detach observer2 from the list
Inputs will be appreciated.