c++vectorsegmentation-faultsmart-pointersraw-pointer

Segfault after deleting elements from vector


I'm currently working on a project, more precisely a tangram game. I have a problem with a segfault and I don't understand why.

Given that I have a whole project, I will try to simplify the problem : I have a GameManager class that contains in particular a Menu object (and other things, but I don't think that is important. The gameManager is used to inititialize this object and manage it. The Menu contains a vector of Button(each button has a lambda to perform an action when the user click on it).

std::vector<std::unique_ptr<Button>> buttons;

To illustrate how it works I will take an example : if the user clicks on the "Load" button, the gameManager delete the current Buttons contained in the menu and add new buttons in that menu.

void GameManager::initMainMenuButtons() {
...
menu -> addButton(std::unique_ptr<Button>(new Button(x1, y1, x2, y2, "Create",
    [this]{
        std::cout << "Create level" << std::endl;
        menu->clear()
        initCreateLevelButtons();
        actionManager->setMenu(menu);
    }
)));
...
}

In that code sample, I have a method initMainMenuButtons that adds several buttons in the menu , like "Load" or "Quit". When the user clicks on "Create", I want to change the interface (adding and deleting buttons). So, to delete the buttons, i call the method clear()

void Menu::clear() {
  buttons.clear();
  decorationPieces.clear(); // not interesting
}

I'm using unique_ptr, thus, I don't have to delete the buttons mannualy. So far, no problem : the vector of buttons seems to be empty (size is 0). Next, the method initCreateLevelButtons() is called. This method is very similar to initMainMenu : it adds buttons in the menu, nothing else. During this call, the buttons seems to be correctly added in the vector, I printed the content of the vector at the end and the vector contains the correct buttons.

And there, the problem appears : after the call of initCreateLevelButtons(), there is a segfault when i want to use the menu, so, actionManager->setMenu(menu); doesn't work. I tried to print the menu std::cout << menu << std::endl, and test if this pointer is nullptr, but it doesn't work either. I don't understand why the menu seems to be correct at the last line of initCreateLevelButtons() and becomes invalid just after. If I doesn't clear the vector of buttons (the menu->clear instruction), the program works, but, the last buttons are still here).

I tried to use raw pointers and I notices that the program is able to clear the vector as long as the buttons are not deleted (If I add a loop to delete the buttons, the problem arises), so, I conclued that the probleme is the buttons deleting. I don't understanf why, I'm stuck. I don't know if I explained it weel, because, as I have already said, the code is part of a whole project, it's hard to introduce classes without introduce other things. if you want details or the complete code of methods, I can provide them.


Solution

    1. menu sustains lifetime of some button
    2. button sustain lifetime of lambda
    3. when you click button lambda clears menu
    4. menu destructor clears button, button clears lambda
    5. lambda continues execution when it in fact has been already destroyed -> undefined behavior ends with a crash

    Now question is: Do you own Button class?
    If yes then the easiest way to fix it, is to invoke copy of lambda in the button.