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.
menu
sustains lifetime of some button
button
sustain lifetime of lambda
button
lambda
clears menu
menu
destructor clears button
, button
clears lambda
lambda
continues execution when it in fact has been already destroyed -> undefined behavior ends with a crashNow 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.