On Aug 24, 2006, at 9:46 AM, Paul Davis wrote:
> 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.

I've banged my head on this problem myself.  It isn't a bug in  
shared_ptr IMHO; I experienced the problem with my own custom-rolled  
smart pointers.

Basically, if a signal object is destroyed as a result of a slot  
being disconnected from it, libsigc++'s basic checks to make sure it  
doesn't double-delete are bypassed.  In the process of disconnecting  
from the slot end, the slot is partially torn down.  It then releases  
its internal stuff, which destroys the signal.  The signal tries to  
disconnect all slots, but this slot is still "in-process" of being  
destroyed.  It's fully destroyed by the signal, but the slot-end  
thinks that it still needs to perform a final delete to finish  
cleaning up the slot.  Voila, double-delete.

When I spent a fair amount of time tracing through the relevant code  
and backtraces, I (unfortunately) didn't see a good way to rectify  
this situation; libsigc++ seems to make all sensible checks.  It  
becomes a problem because (IIRC) slot_rep is deleted from the signal  
end as a result of the invocation of a slot_rep method, and that  
method tries to do one more cleanup action after the line that  
results in the deletion occurs.  Result: there's a method still  
running though its object has been deleted, and it blows up.

My conclusion walking away from the matter was that the best solution  
is just to avoid storing reference-counting pointers in slots; using  
a bald pointer or weak pointer is a better option.  This should  
probably be documented somewhere, though.

- Michael
_______________________________________________
libsigc-list mailing list
libsigc-list@gnome.org
http://mail.gnome.org/mailman/listinfo/libsigc-list

Reply via email to