Dispatched lambda not reading the correct addresses?

48 Views Asked by At

For some context, I'm trying to build a GUI application, and at some point I need to build a widget and retrieve some data (in another thread, but for now I'm doing it in the main thread), this data will be stored in an object wrapped by a shared_ptr.

The shared_ptr contents will be accessed on the main thread by a lambda executed by a Glib::Dispatcher, for some reason however, it seems that the shared_ptr gets deleted before (or once) the dispatcher gets called.

Note that the shared_ptr is tied to the lifetime of the class, even though it is initialized in the constructor.

A bit of sample code:

Header File

class ExploreView : public Gtk::Box
{
public:
    ExploreView(std::shared_ptr<Gtk::Window> parent_window);
public:
    // Explore Object
    std::shared_ptr<backend::Explore> explore; // The pointer!
    // Featured Shows Previews
    std::shared_ptr<Glib::Dispatcher> featured_callback;
};

Snippet from the class constructor

featured_callback = std::make_shared<Glib::Dispatcher>();
featured_callback->connect([this]() {
    std::cout << "Dispatched!" << std::endl;
    std::cout << "USE COUNT: " << explore.use_count() << std::endl;
});

explore = std::make_shared<backend::Explore>();
std::cout << "USE COUNT: " << explore.use_count() << std::endl;
featured_callback->emit();

As you can see, I'm allocating the Glib::Dispatcher, connect a lambda to it, and then writing inside some dumb code to print a string and check the use count of the shared_ptr.

This code is not called yet.

Afterwards I'm initializing the explore shared_ptr, printing the use count (which is 1, as expected) and finally I'm calling the Glib::Dispatcher (the lambda that I "connected" to it previously.

I would expect the lambda to happily print 1, instead it segfaults. But I can't understand why, the pointer lifetime should be tied to the class, not the constructor, if that's even the problem to begin with.

This behavior seems weird to me, so for testing only I switched to a raw C pointer.

Updated code as sample:

Updated header file

class ExploreView : public Gtk::Box
{
public:
    ExploreView(std::shared_ptr<Gtk::Window> parent_window);
public:
    // Explore Object
    backend::Explore* explore;
    // Featured Shows Previews
    std::shared_ptr<Glib::Dispatcher> featured_callback;
};

Updated snippet from class constructor

featured_callback = std::make_shared<Glib::Dispatcher>();
featured_callback->connect([this]() {
    std::cout << "Dispatched!" << std::endl;
    // This is a vector of which size is always 10
    std::cout << "Retrieved size: " << explore->featured_anime_ids.size() << std::endl;
});

explore = new backend::Explore();
featured_callback->emit();

This didn't work either.

Consider that the Explore object contains the member featured_anime_ids which is a vector<int> of which size is always 10.

For some reason, when accessing it from the dispatched lambda, I always get size 18446743979220271125 no matter how many times I run it. Trying to allocate any buffer from the dispatched lambda results in a segmentation fault.

I also tried printing the address of the shared_ptr from outside the dispatched lambda and from within the dispatched lambda, and I noticed that the address changed. Using the debugger, I also saw at some point the content of the pointer changed.

While writing I did some more testing with the debugger.

It seems that the buffer stays in memory as it should, but the shared_ptr is changing it's address (and so I suppose also the raw pointer) making the lambda read and write to random buffers in memory and therefore rightfully going into segault.

But I do not understand what is causing this behavior.

I'm also not sure of what other testing I could do, any help is immensely appreciated.

Thanks in advance.

0

There are 0 best solutions below