The following program outputs a segmentation fault (core dumped). I need help figuring out what is wrong. Thanks in advance

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#include <iostream>
#include <algorithm>
#include <string>
#include <map>

using namespace std;

class Component;

//Medical Devices
class MedicalEntity {
    public:
        MedicalEntity(Component*, const string&); 
        virtual string get_name() const;
        virtual void update() = 0;
        virtual void receive(double) = 0;
        virtual ~MedicalEntity();
    protected:
        Component* msg_component;
        string m_name;

};

class Component { 
    public:
        virtual void send(MedicalEntity*, double) = 0;
        virtual ~Component(){cout <<"Component destructor"<< endl;}
};

//Mediator Interface
class IMediator {
    public:
        virtual ~IMediator(){ cout <<"IMediator destructor"<<endl;}
        virtual void register_subscriber(MedicalEntity*, const string) = 0;
        virtual void register_publisher(MedicalEntity*, const string) = 0;
        virtual void send(MedicalEntity*, double) = 0;
};

class Mediator: public IMediator {
    public:
        Mediator(){}
        virtual ~Mediator();
        virtual void register_subscriber(MedicalEntity*, const string);
        virtual void register_publisher(MedicalEntity*, const string);
        virtual void send(MedicalEntity*, double);
    protected:
        multimap<const string, MedicalEntity*> subscriber_registry;
        map<string, string> publisher_registry; 
};

//Publish
class MessageComponent : public Component {
    public:
        MessageComponent(IMediator*);
        virtual void send(MedicalEntity*, double);
        virtual ~MessageComponent();
    protected:
        IMediator* m_mediator;
};

//Monitor
class Monitor : public MedicalEntity {
    public:
        Monitor(Component*, const string&);
        virtual void update();
        virtual void receive(double);
        virtual ~Monitor();
    private:
        double heart_rate;
        double pressure;
};

//Controller
class Controller : public MedicalEntity {
    public:
        Controller(Component*, const string&);
        virtual void update();
        virtual void receive(double);
        virtual ~Controller();
    private:
        double rate;
};

//Pump
class Pump : public MedicalEntity {
    public:
        Pump(Component*, const string&);
        virtual void update();
        virtual void receive(double);
        virtual ~Pump();
    private:
        double rate;
};


//Main
int main() {
    
    Mediator mediator;

    /*
     * @params -> (MedicalEntity*, Topic name)
     */
    Monitor monitor{new MessageComponent(&mediator),"monitor1"};
    Controller controller{new MessageComponent(&mediator), "controller1"};
    Pump saline_pump{new MessageComponent(&mediator), "saline"};
    Pump bp_drug_pump{new MessageComponent(&mediator), "Norepinephrine"};
    
    mediator.register_publisher(&monitor, "monitor");
    mediator.register_subscriber(&controller, "monitor");
    mediator.register_publisher(&controller, "controller");
    mediator.register_subscriber(&saline_pump, "controller");
    mediator.register_subscriber(&bp_drug_pump, "controller");

    monitor.update();
    controller.update();
    saline_pump.update();
    bp_drug_pump.update();

    return 0;
}



MedicalEntity::MedicalEntity(Component* component, const string& name) : 
msg_component{component}, m_name{name} {

}

string MedicalEntity::get_name() const {
    return m_name;
}

MedicalEntity::~MedicalEntity() {
    cout << "MedicalEntity destructor" << endl;
    delete msg_component;
    msg_component = nullptr;
}

// MessageComponent Implementation
MessageComponent::MessageComponent(IMediator* mediator) : 
m_mediator{mediator} {

}

void MessageComponent::send(MedicalEntity* entity, double value) {
    m_mediator->send(entity, value);
}

MessageComponent::~MessageComponent(){ 
    cout << "MessageComponent destructor"<< endl;
    delete m_mediator;
    m_mediator = nullptr;
}

//Monitor Implementation
Monitor::Monitor(Component* component, const string& name) : 
MedicalEntity{component, name} {
     cout << "Monitor created..."<<endl;
}

void Monitor::receive(double value) {
    cout << "Monitor received value: "<< value << endl;
}

void Monitor::update() {
    heart_rate = rand() % 100 + 10;
    cout << "Monitor running..." << endl;
    cout << "Monitor sent new heart rate "<<heart_rate<<" to controller"<< endl;
    msg_component->send(this, heart_rate);
}

Monitor::~Monitor() {
    cout <<"Monitor destructor"<<endl;
}

//Controller Implementation
Controller::Controller(Component* component, const string& name): 
MedicalEntity{component, name} {
    cout<< "Controller created ..."<<endl;
}

void Controller::update() {
    cout << "Controller running..." << endl;
    rate = rand() % 50 + 50;
    cout << "Controller sent new rate "<< rate <<" to Pump"<< endl;
    msg_component->send(this, rate);
}

void Controller::receive(double hr) {
    cout << "Controller received heart rate value: "<< hr << endl;
}

Controller::~Controller() {
    {cout <<"Controller destructor"<<endl;}
}

//Pump Implementation
Pump::Pump(Component* component, const string& name) : 
MedicalEntity{component, name} {
    cout<< get_name()<< " Pump created ..."<<endl;
}

void Pump::receive(double rate) {
    cout << get_name() << " Pump received new rate value: "<< rate << endl;
}

void Pump::update() {
    cout << get_name() <<" pump is running..."<< endl;
}

Pump::~Pump() {
    {cout << "Pump destructor"<<endl;}
}

//Mediator Implementation
void Mediator::register_publisher(MedicalEntity* pub, const string topic) {
    string publisher = pub->get_name();
    auto it = publisher_registry.find(publisher);

    if(it == publisher_registry.end()) {
        publisher_registry[publisher] = topic;
        cout << publisher << " will publish on: " << topic <<endl;
    }
}

void Mediator::register_subscriber(MedicalEntity* sub, const string topic) {
    subscriber_registry.insert(make_pair(topic, sub));
    cout << sub->get_name() <<" has subscribed to: "<< topic << endl;
}

void Mediator::send(MedicalEntity* pub, double value) {
    string publisher = pub->get_name();
    string topic = publisher_registry[publisher];
    auto subscriber_entries= subscriber_registry.equal_range(topic);
    
    for_each(subscriber_entries.first, 
            subscriber_entries.second,
            [value](pair<const string, MedicalEntity*> const& subscriber_entry){ 
                auto const& subscriber = subscriber_entry.second;
                subscriber->receive(value); });
}

Mediator::~Mediator(){   
    cout << "Mediator destructor" << endl;  

    for_each(subscriber_registry.begin(), 
             subscriber_registry.end(),
             [](pair<const string, MedicalEntity*>& subscriber_entry) { 
                 delete subscriber_entry.second; });
}

Last edited on
throw us a bone here.
run it in the debugger and figure out where it was when it crashed, or stick some flushed print statements into it, or something...
This is an example of what jonnin means.

Compile with the "-g" flag to get lots of useful information in the debugger.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
$ g++ -std=c++11 -Wall -Wextra -g proj.cpp
$ gdb -q ./a.out 
Reading symbols from ./a.out...done.
(gdb) run
Starting program: /home/sc/Documents/a.out 
Monitor created...
Controller created ...
saline Pump created ...
Norepinephrine Pump created ...
monitor1 will publish on: monitor
controller1 has subscribed to: monitor
controller1 will publish on: controller
saline has subscribed to: controller
Norepinephrine has subscribed to: controller
Monitor running...
Monitor sent new heart rate 93 to controller
Controller received heart rate value: 93
Controller running...
Controller sent new rate 86 to Pump
saline Pump received new rate value: 86
Norepinephrine Pump received new rate value: 86
saline pump is running...
Norepinephrine pump is running...
Pump destructor
MedicalEntity destructor
MessageComponent destructor
Mediator destructor
Pump destructor
MedicalEntity destructor
MessageComponent destructor
Mediator destructor

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0  0x0000000000000000 in ?? ()
#1  0x0000000000402786 in Mediator::~Mediator()::{lambda(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, MedicalEntity*>&)#1}::operator()(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, 
    std::allocator<char> > const, MedicalEntity*>&) const () at proj.cpp:250
#2  0x0000000000402952 in std::for_each<std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, MedicalEntity*> >,
    Mediator::~Mediator()::<lambda(std::pair<const std::__cxx11::basic_string<char>, MedicalEntity*>&)> >(std::_Rb_tree_iterator<std::pair<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const, MedicalEntity*> >, std::_Rb_tree_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>,
    std::allocator<char> > const, MedicalEntity*> >,
    Mediator::<lambda(std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, MedicalEntity*>&)>) (__first=..., __last=..., __f=...) at /usr/include/c++/5/bits/stl_algo.h:3767
#3  0x0000000000402804 in Mediator::~Mediator (this=0x7fffffffdbb0, __in_chrg=<optimised out>) at proj.cpp:250
#4  0x000000000040287e in Mediator::~Mediator (this=0x7fffffffdbb0, __in_chrg=<optimised out>) at proj.cpp:251
#5  0x0000000000401c54 in MessageComponent::~MessageComponent (this=0x61c070, __in_chrg=<optimised out>) at proj.cpp:152
#6  0x0000000000401c9c in MessageComponent::~MessageComponent (this=0x61c070, __in_chrg=<optimised out>) at proj.cpp:154
#7  0x0000000000401b16 in MedicalEntity::~MedicalEntity (this=0x7fffffffdd80, __in_chrg=<optimised out>) at proj.cpp:136
#8  0x0000000000402364 in Pump::~Pump (this=0x7fffffffdd80, __in_chrg=<optimised out>) at proj.cpp:212
#9  0x0000000000402394 in Pump::~Pump (this=0x7fffffffdd80, __in_chrg=<optimised out>) at proj.cpp:214
#10 0x0000000000402786 in Mediator::~Mediator()::{lambda(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>,
    std::allocator<char> > const, MedicalEntity*>&)#1}::operator()(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, MedicalEntity*>&) const () at proj.cpp:250
#11 0x0000000000402952 in std::for_each<std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, MedicalEntity*> >,
    Mediator::~Mediator()::<lambda(std::pair<const std::__cxx11::basic_string<char>, MedicalEntity*>&)> >(std::_Rb_tree_iterator<std::pair<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const, MedicalEntity*> >, std::_Rb_tree_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>,
 std::allocator<char> > const, MedicalEntity*> >, Mediator::<lambda(std::pair<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, MedicalEntity*>&)>) (__first=..., __last=..., __f=...) at /usr/include/c++/5/bits/stl_algo.h:3767
#12 0x0000000000402804 in Mediator::~Mediator (this=0x7fffffffdbb0, __in_chrg=<optimised out>) at proj.cpp:250
#13 0x000000000040287e in Mediator::~Mediator (this=0x7fffffffdbb0, __in_chrg=<optimised out>) at proj.cpp:251
#14 0x0000000000401c54 in MessageComponent::~MessageComponent (this=0x61c090, __in_chrg=<optimised out>) at proj.cpp:152
#15 0x0000000000401c9c in MessageComponent::~MessageComponent (this=0x61c090, __in_chrg=<optimised out>) at proj.cpp:154
#16 0x0000000000401b16 in MedicalEntity::~MedicalEntity (this=0x7fffffffddc0, __in_chrg=<optimised out>) at proj.cpp:136
#17 0x0000000000402364 in Pump::~Pump (this=0x7fffffffddc0, __in_chrg=<optimised out>) at proj.cpp:212
#18 0x00000000004017ff in main () at proj.cpp:107
(gdb) 


So you start at frame #18 in main() at line 107, which called the Pump dtor.
In frame #17, Pump dtor is destructing a MedicalEntity.
And so on.

> #0 0x0000000000000000 in ?? ()
This means you tried to call a nullptr.
Any suggestions on how to fix it
I guess you can start looking at frames 9 and 10, and figuring out what is wrong with Mediator destructing Pump, when at frame 17, it's Pump that destructs Mediator.

In other words, you've built a nice cyclic dependency of destruction.

Figure out who is responsible for what.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
MessageComponent::~MessageComponent() {
	cout << "MessageComponent destructor" << endl;
	delete m_mediator;  //¡!
	m_mediator = nullptr;
}

Mediator::~Mediator() {
	cout << "Mediator destructor" << endl;

	for_each(
	    subscriber_registry.begin(),
	    subscriber_registry.end(),
	    [](pair<const string, MedicalEntity *> &subscriber_entry) {
		    delete subscriber_entry.second;  //¡!
	    });
}

	Mediator mediator; //not created with `new'
	/*
	 * @params -> (MedicalEntity*, Topic name)
	 */
	Monitor monitor{new MessageComponent(&mediator), "monitor1"};
	Controller controller{new MessageComponent(&mediator), "controller1"};
	Pump saline_pump{new MessageComponent(&mediator), "saline"};
	Pump bp_drug_pump{new MessageComponent(&mediator), "Norepinephrine"};
	//at their destructor, those four object will destroy its `msg_component', which in turn will try to delete `mediator'
	//deleting four times something that was not created with `new'

	mediator.register_publisher(&monitor, "monitor");
	mediator.register_subscriber(&controller, "monitor");
	mediator.register_publisher(&controller, "controller");
	mediator.register_subscriber(&saline_pump, "controller");
	mediator.register_subscriber(&bp_drug_pump, "controller");
	//at its destructor, `mediator' will kill its subscriber, none of which was created with `new' 
https://en.cppreference.com/w/cpp/memory/weak_ptr
https://en.cppreference.com/w/cpp/memory/shared_ptr
https://en.cppreference.com/w/cpp/memory/unique_ptr
and dont delete what you didn't new

a small explanation of what you were trying to do and how your classes are related would have helped a lot.
Last edited on
Thank you all for the hints you provided. The issue was resolved after switching all my raw pointers pointers to smart ones.

I am trying develop a closed-loop simulation framework mimicking physiology control in an operating room/ICU. The diagnosis and therapeutic process will be handled by the algorithm that will reside in the controller. I will be using virtual patient, whose physiology variables are captured by the 'monitor' which then sends these variables to the to the 'controller' and depending on the patient's status the controller then instructs the pump to adjust the infusion rate of whatever drug the patient is being given (this process continues for predefined duration or until 'patient' gets better )

The code above was me trying to figure how the medical components will communicate during the simulation.

Thanks again.
Last edited on
Topic archived. No new replies allowed.