T
tom
I have the section of code listed below, but when I return from main
an exception is thrown from the library, because while returning,
destructor is called on each of the object in the sequence below:
step1: destroy m2
step2: destroy f
step3: destroy m1
notice, "m1" and "m2" have the class type of Message, and will both
use object "f" in the destructor. The problem happens when run to
step3, it uses an already destroyed object f. (dangling pointer).
My question is: Is there any known solution or design pattern to solve
this problem?
#include <iostream>
#include <vector>
#include <hash_map>
#include <cctype>
#include <cassert>
#include <fstream>
#include <sstream>
#include <list>
#include <deque>
#include <algorithm>
#include <numeric>
#include <stack>
#include <queue>
#include <map>
#include <set>
class Message;
class Folder
{
public:
void add_Msg(Message*);
void remove_Msg(Message*);
~Folder()
{
std::cout<<"~Folder()"<<std::endl;
}
private:
std::set<Message*> messages;
};
void Folder::add_Msg(Message* m)
{
messages.insert(m);
}
void Folder::remove_Msg(Message* m)
{
messages.erase(m);
}
class Message
{
public:
Message(const std::string &str = ""):contents(str){}
Message(const Message&);
Message& operator=(const Message&);
~Message();
void save(Folder&);
void remove(Folder&);
private:
std::string contents;
std::set<Folder*> folders;
void put_Msg_in_Folders(const std::set<Folder*>&);
void remove_Msg_from_Folders();
};
Message::Message(const Message& m):contents(m.contents),
folders(m.folders)
{
put_Msg_in_Folders(m.folders);
}
Message& Message:perator=(const Message& m)
{
remove_Msg_from_Folders();
put_Msg_in_Folders(m.folders);
contents = m.contents;
folders = m.folders;
return *this;
}
Message::~Message()
{
remove_Msg_from_Folders();
}
void Message::save(Folder& f)
{
folders.insert(&f);
f.add_Msg(this);
}
void Message::remove(Folder& f)
{
folders.erase(&f);
f.remove_Msg(this);
}
void Message:ut_Msg_in_Folders(const std::set<Folder*>& f)
{
std::set<Folder*>::const_iterator iter = f.begin();
while(iter!=f.end())
{
(*iter)->add_Msg(this);
++iter;
}
}
void Message::remove_Msg_from_Folders()
{
std::set<Folder*>::iterator iter = folders.begin();
std::cout<<reinterpret_cast<int>(*iter)<<std::endl;
while(iter!=folders.end())
{
(*iter)->remove_Msg(this);
++iter;
}
}
int main(int argc, char *argv[])
{
Message m1("s");
Folder f;
m1.save(f);
Message m2(m1);
m2 = m1;
return 0;
}
an exception is thrown from the library, because while returning,
destructor is called on each of the object in the sequence below:
step1: destroy m2
step2: destroy f
step3: destroy m1
notice, "m1" and "m2" have the class type of Message, and will both
use object "f" in the destructor. The problem happens when run to
step3, it uses an already destroyed object f. (dangling pointer).
My question is: Is there any known solution or design pattern to solve
this problem?
#include <iostream>
#include <vector>
#include <hash_map>
#include <cctype>
#include <cassert>
#include <fstream>
#include <sstream>
#include <list>
#include <deque>
#include <algorithm>
#include <numeric>
#include <stack>
#include <queue>
#include <map>
#include <set>
class Message;
class Folder
{
public:
void add_Msg(Message*);
void remove_Msg(Message*);
~Folder()
{
std::cout<<"~Folder()"<<std::endl;
}
private:
std::set<Message*> messages;
};
void Folder::add_Msg(Message* m)
{
messages.insert(m);
}
void Folder::remove_Msg(Message* m)
{
messages.erase(m);
}
class Message
{
public:
Message(const std::string &str = ""):contents(str){}
Message(const Message&);
Message& operator=(const Message&);
~Message();
void save(Folder&);
void remove(Folder&);
private:
std::string contents;
std::set<Folder*> folders;
void put_Msg_in_Folders(const std::set<Folder*>&);
void remove_Msg_from_Folders();
};
Message::Message(const Message& m):contents(m.contents),
folders(m.folders)
{
put_Msg_in_Folders(m.folders);
}
Message& Message:perator=(const Message& m)
{
remove_Msg_from_Folders();
put_Msg_in_Folders(m.folders);
contents = m.contents;
folders = m.folders;
return *this;
}
Message::~Message()
{
remove_Msg_from_Folders();
}
void Message::save(Folder& f)
{
folders.insert(&f);
f.add_Msg(this);
}
void Message::remove(Folder& f)
{
folders.erase(&f);
f.remove_Msg(this);
}
void Message:ut_Msg_in_Folders(const std::set<Folder*>& f)
{
std::set<Folder*>::const_iterator iter = f.begin();
while(iter!=f.end())
{
(*iter)->add_Msg(this);
++iter;
}
}
void Message::remove_Msg_from_Folders()
{
std::set<Folder*>::iterator iter = folders.begin();
std::cout<<reinterpret_cast<int>(*iter)<<std::endl;
while(iter!=folders.end())
{
(*iter)->remove_Msg(this);
++iter;
}
}
int main(int argc, char *argv[])
{
Message m1("s");
Folder f;
m1.save(f);
Message m2(m1);
m2 = m1;
return 0;
}