Hi,

I noticed that if a trackable object is freed from inside the slot which is setup to track this object then the slot is immediately invalidated. Problem arises when such a slot holds a lambda which captures some other variables by-value or some variables are bound by value to the slot. In such cases the invalidation of the slot causes all bound object instances to be immediately freed.

I have attached a test case patch (for the current master) which demonstrates the issue using lambda captures and sigc::bind bounds.

    My question: is it a bug or it's supposed to work like that?

The patch also contains a 3rd test which disconnects the slot explicitly from inside the lambda slot with captured variables, but in this case it doesn't cause captured variables to be freed right from inside the slot. So I'm inclined to think that track_obj should behave in a similar safe way.

BR, Andrey
diff --git a/tests/test_track_obj.cc b/tests/test_track_obj.cc
index 0680508..9c20b30 100644
--- a/tests/test_track_obj.cc
+++ b/tests/test_track_obj.cc
@@ -36,6 +36,7 @@
 #include "testutilities.h"
 #include <iostream>
 #include <sigc++/adaptors/track_obj.h>
+#include <sigc++/adaptors/bind.h>
 #include <sigc++/signal.h>
 
 namespace
@@ -112,6 +113,18 @@ foo_group4(bar_group4&)
   result_stream << "foo_group4(bar_group4&)";
 }
 
+struct foo_data
+{
+    ~foo_data() { magic = -42; }
+    int magic = 42;
+};
+
+int foo_fun(const foo_data& data, bar_group4* bar)
+{
+    delete bar;
+    return data.magic;
+}
+
 } // end anonymous namespace
 
 int
@@ -213,5 +226,34 @@ main(int argc, char* argv[])
     util->check_result(result_stream, "");
   }
 
+  {
+      // Free trackable object from inside the slot which tracks it
+      auto bar = new bar_group4();
+      foo_data data;
+      auto lambda = [data, bar]() { delete bar; return data.magic; };
+      sigc::slot<int()> sl = sigc::track_obj(lambda, *bar);
+      result_stream<<sl();
+      util->check_result(result_stream, "42");
+  }
+
+  {
+      // Free trackable object from inside the slot which tracks it
+      auto bar = new bar_group4();
+      foo_data data;
+      sigc::slot<int()> sl = sigc::track_obj(sigc::bind(sigc::ptr_fun(foo_fun), data, bar), *bar);
+      result_stream<<sl();
+      util->check_result(result_stream, "42");
+  }
+
+  {
+      // Disconnect a slot from inside itself
+      sigc::slot<int()> sl;
+      foo_data data;
+      auto lambda = [data, &sl]() { sl.disconnect(); return data.magic; };
+      sl = lambda;
+      result_stream<<sl();
+      util->check_result(result_stream, "42");
+  }
+
   return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE;
 }
_______________________________________________
libsigc-list mailing list
libsigc-list@gnome.org
https://mail.gnome.org/mailman/listinfo/libsigc-list

Reply via email to