Segmentation faul on lambda call

This might be more of a C++ question, but the forum description says these are welcome here as well :innocent:

I have a very basic derivative class of ComboBox which has a std::function<void()> rearrangeMenu to create the menu dynamically from the parent class when a mouse click occurs. But manipulating the object itself within the lambda seems to create an segmentation fault:

// in PluginEditor.h

GlasDisplay display; 

...

// in PluginEditor() constructor

display.rearrangeMenu = [&]() {
    //Any of the following will cause a segfault on function call (in MouseDown())
    display.clear();
    display.addItem("segfault", 1);
    display.getRootMenu()->clear();
};

Any help appreciated! :slight_smile:

If the code is literally like that in a function, you are capturing the local variable “display” by reference into the lambda. When the function ends, the local variable is gone and the lambda will later be trying to use the deleted object.

display is a member of the PluginEditor and doesn’t run out of scope. Ok, I should have added that info and will correct it now in the first post.

Shouldn’t you be using [this] instead of [&] if display is a member of this object?

Capturing [&] implies “this” is captured too. (I would personally prefer capturing “this” and really all other variables too explicitly though.)

1 Like

Ok I figured it out, the (boiled down) example in my first post is actually ok, but here’s what’s not:

// in PluginEditor.h

GlasDisplay display[MAX]; 

...

// in PluginEditor() constructor
for(int i = 0; i < MAX; ++i){
    display[i].rearrangeMenu = [&]() {
        //capturing i by reference produces segfault, since it only lives in the forloop
        display[i].clear();
        display[i].addItem("segfault", 1);
        display[i].getRootMenu()->clear();
    };
}

So after all you couldn’t have solved it with the information I gave you… Thanks for your answers anyway! :slight_smile:

1 Like

Just a side note:
If you capture anything else than the structure, that owns the lambda, it is advisable to capture any kind of smart pointer, that ensures the captured object is still valid.
You can use from juce: WeakReference<MyThing> or SafePointer<ComponentHeir>
Or from std: std::weak_ptr (to point to a std::shared_ptr).

Then check in your lambda for nullptr:

WeakReference<MyThing> thing (realThing);
display[i].rearrangeMenu = [thing]()
{
    if (thing.get() == nullptr)
        return;
    // safe to use thing now, unless construction or destruction happens on a different thread
};
2 Likes