Re: [sigc] C++11 'auto' with sigc::mem_fun doesn't track object lifetime (potential crash)





On Wed, Mar 2, 2016 at 7:45 AM, Andrejs Hanins <andrejs hanins ubnt com> wrote:
Hi,

    Consider simple code below which results in Foo::Call method to be actually called for _deleted instance_:

    class Foo : public sigc::trackable  {
        public:
        void Call() { printf("Foo call\n"); }
    };

    Foo* inst = new Foo();
    auto fun = sigc::mem_fun(inst, &Foo::Call); // <-- bad
    //sigc::slot<void> fun = sigc::mem_fun(inst, &Foo::Call); // <-- good
    delete inst;
    fun(); // <--- ooops!


    The documentation for mem_fun says that "...only if the object type inherits from sigc::trackable <https://developer.gnome.org/libsigc++/stable/structsigc_1_1trackable.html> is the slot automatically cleared...", but the problem is that result of mem_fun is not a slot, but a bound_mem_fun which for some reason doesn't track referenced object lifetime even if it inherits from trackable. If result of mem_fun is put explicitly into a slot, then everything works fine and Call() method is not called after instance is freed.

    For me it looks like a typical "shoot in the foot" for C++11 programs and should be indeed fixed. Just in case - issue is reproducible in current master too.

your expectations are too high. the behaviour of sigc::trackable as documented applies ONLY to a slot.

a sigc::mem_fun is just a closure, aka a functor aka a functor object aka an invokable object. it has not semantics beyond operator(). In C terms, it is really nothing more than:

     struct {
         SomeThing* instance_of_thing;
         ReturnType (*function_taking_something)(SomeThing*);
     };

and operator() is just a call to function_taking_something (instance_of_thing); there are no magic semantics here, no lifetime tracking. this is intentional (and correct).

if you want the behaviour of sigc::trackable, then you MUST use sigc::slot.  there's no "shoot in the foot" issue here.
 
the same behaviour applies to boost::bind() for example, which also returns a functor/closure.


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