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