[sigc] sigc slot & shared_ptr anti-pattern



below is a tiny program that demonstrates either an anti-pattern or a
bug or both in the use/design of libsigc++. the program will generally
run normally, but using valgrind reveals something deeply wrong, as
noted in the annotations in the code.

the basic rule seems to be that you must never, ever put a shared_ptr<T>
into a slot if:

	1) T has a sigc::signal
	2) the slot could end up being the last instance of shared_ptr<T> to
this particular "T"

keep in mind that the lifetime of "b" in the example is artificially
short. all that really matters is that b's lifetime would have ended
before that of a if it was not referenced by a shared_ptr in a slot
belonging to a.

comments welcome. 

--p

#include <boost/shared_ptr.hpp>
#include <sigc++/sigc++.h>

class B;

class A : public sigc::trackable 
{
    public:
        A () {}
    
        void signal_handler (boost::shared_ptr<B>) {};
};

class B : public sigc::trackable
{
    public:
        B () {}

        sigc::signal<void> MySignal;
};

int
main (int argc, char* argv[])
{
	{
		boost::shared_ptr<A> a (new A);
		
		{
			boost::shared_ptr<B> b (new B);

			b->MySignal.connect (sigc::bind (sigc::mem_fun (*(a.get()),
&A::signal_handler), b));

			// new B continues to exist even as b goes out of scope because
			// it now exists in the slot connected to b.MySignal
		}

		// 1) a goes out scope, deletes new A
		// 2) a's sigc::trackable starts cleaning up its slots
		// 3) it finds one and deletes it
		// 4) shared_ptr<B> in the slot executes its destructor, 
		// 5) shared_ptr<B> holds last reference to new B
		// 6) ~B starts cleaning up
		// 7) destroys its sigc::signal
		// 8) the signal cleans up all slots connected to it
		// 9) but one of its slots is the one being deleted in step 3
		// 10) ~B finishes
		// 11) return to end of slot destruction at step 3
		// 12) double delete accomplished, boom!
	}

	return 0;
}






[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]