Reputation: 78
I am trying to write a boost-signal like class (as practice to learn c++). And I found when I use enable_shared_from_this
, I always got crash in destructor. Here is the code (I am using vs2012 update 2):
Any comment on this? This issue should be caused shared_from_this()
, because when I uncomment the line (auto this_ = shared_from_this();
) in signal_connection::disconnect
, everything works fine.
I know it must at least has one valid shared_ptr before calling shared_from_this()
. My code should satisfy this.
Code:
#include <memory>
#include <map>
class slot_manager;
class signal_connection: public std::enable_shared_from_this<signal_connection>
{
public:
signal_connection(slot_manager* manager)
:manager_(manager)
{}
public:
void disconnect() ;
private:
slot_manager* manager_;
};
class slot_manager
{
public:
typedef std::shared_ptr<signal_connection> connection_type;
typedef std::map<connection_type, int> map_type;
typedef map_type::value_type map_value_type;
public:
void connect(int slot)
{
std::shared_ptr<signal_connection> c(new signal_connection(this));
slots_.insert(map_value_type(c, slot));
}
~slot_manager()
{
auto iter = slots_.begin();
map_type::iterator iter2 = slots_.end();
while (iter != slots_.end())
{
iter2 = iter++;
iter2->first->disconnect();
}
}
void disconnect(std::shared_ptr<signal_connection> connection)
{
auto c = slots_.find(connection);
if (c != slots_.end())
{
slots_.erase(c);
}
}
protected:
map_type slots_;
};
void signal_connection::disconnect()
{
if (manager_ != nullptr)
{
//auto this_ = shared_from_this();
manager_->disconnect(shared_from_this());
manager_ = nullptr;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
slot_manager x;
x.connect(1);
return 0;
}
Upvotes: 1
Views: 1409
Reputation: 15997
The problem is that the signal_connection is detroyed in disconnect()
before you set its manager to nullptr
, which then causes an access violation, i.e. by the call to the manager's disconnect. This is because the manager holds the only shared_ptr
to the connection, and you erase()
that. The object doesn't keep itself alive. Unless, of course, you uncomment that line. this_
just lives long enough to circumvent the problem.
Upvotes: 7