Re: [sigc] C++11 'auto' with sigc::mem_fun doesn't track object lifetime (potential crash)
- From: Andrejs Hanins <andrejs hanins ubnt com>
- To: Paul Davis <paul linuxaudiosystems com>
- Cc: Libsigc++ <libsigc-list gnome org>
- Subject: Re: [sigc] C++11 'auto' with sigc::mem_fun doesn't track object lifetime (potential crash)
- Date: Wed, 2 Mar 2016 15:22:53 +0200
Hi Paul,
On 03/02/2016 03:10 PM, Paul Davis wrote:
On Wed, Mar 2, 2016 at 7:45 AM, Andrejs Hanins <andrejs hanins ubnt com <mailto: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.
That makes sense, but isn't documentation still confusing, as it mentions 'slot' when speaking about mem_fun.
Slot is indeed present in the example code below mem_fun description, but it is not obvious which 'slot' the
sentence is talking about. I'm not insisting on this, just a space for a potential improvement. Maybe change
the docs to "Note that _in the example below_ only if the object..."
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]