Article 5MF9R cyclic dependency of shared ptr, not allowing destructor to invoke

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.latest?d=yIl2AUoC8zA latest?i=ZOlzfusgUEU:RpygKmKfW08:F7zBnMy latest?i=ZOlzfusgUEU:RpygKmKfW08:V_sGLiP latest?d=qj6IDK7rITs latest?i=ZOlzfusgUEU:RpygKmKfW08:gIN9vFwZOlzfusgUEU
External Content
Source RSS or Atom Feed
Feed Location https://feeds.feedburner.com/linuxquestions/latest
Feed Title LinuxQuestions.org
Feed Link https://www.linuxquestions.org/questions/
Reply 0 comments