7 years, 4 months ago.

setup menu by a function?

Hi, why does the initialisation of the Menu only works if put in main? What am I missing?

This doesn't work:

#include "Menu.h"

int cursorPos = 0;
Menu *activeMenu;

void print_menu()
{
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("%s", activeMenu->menuID);
    lcd.locate(0,1);
    lcd.printf("%s", activeMenu->selections[cursorPos].selText);
}

void setup_menu()
{

    Menu settingsMenu("SettingsID");

    Menu ch0Menu("ch0MenuID");
    ch0Menu.add(Selection(NULL, 0, NULL, "Manual"));
    ch0Menu.add(Selection(NULL, 1, NULL, "Auto"));
    
    Menu ch1Menu("ch1MenuID");
    ch1Menu.add(Selection(NULL, 0, NULL, "Manual"));
    ch1Menu.add(Selection(NULL, 1, NULL, "Auto"));
    
    Menu ch2Menu("ch2MenuID");
    ch2Menu.add(Selection(NULL, 0, NULL, "Manual"));
    ch2Menu.add(Selection(NULL, 1, NULL, "Auto"));

    settingsMenu.add(Selection(NULL, 0, &ch0Menu, "<ch0menu>"));
    settingsMenu.add(Selection(NULL, 1, &ch1Menu, "<ch1menu>"));
    settingsMenu.add(Selection(NULL, 2, &ch2Menu, "<ch2menu>"));

    activeMenu = &settingsMenu;
}

int main()
{
    setup_menu();
    print_menu();

    while(1) {
        wait(1);
    }
}

While this works!

#include "Menu.h"

int cursorPos = 0;
Menu *activeMenu;

void print_menu()
{
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("%s", activeMenu->menuID);
    lcd.locate(0,1);
    lcd.printf("%s", activeMenu->selections[cursorPos].selText);
}


int main()
{

    Menu settingsMenu("SettingsID");

    Menu ch0Menu("ch0MenuID");
    ch0Menu.add(Selection(NULL, 0, NULL, "Manual"));
    ch0Menu.add(Selection(NULL, 1, NULL, "Auto"));
    
    Menu ch1Menu("ch1MenuID");
    ch1Menu.add(Selection(NULL, 0, NULL, "Manual"));
    ch1Menu.add(Selection(NULL, 1, NULL, "Auto"));
    
    Menu ch2Menu("ch2MenuID");
    ch2Menu.add(Selection(NULL, 0, NULL, "Manual"));
    ch2Menu.add(Selection(NULL, 1, NULL, "Auto"));

    settingsMenu.add(Selection(NULL, 0, &ch0Menu, "<ch0menu>"));
    settingsMenu.add(Selection(NULL, 1, &ch1Menu, "<ch1menu>"));
    settingsMenu.add(Selection(NULL, 2, &ch2Menu, "<ch2menu>"));

    activeMenu = &settingsMenu;

    print_menu();

    while(1) {
        wait(1);
    }
}

Question relating to:

Library of menu structure

2 Answers

7 years, 4 months ago.

It's only a guess, but "settingsMenu", "ch0Menu", "ch1Menu", and "ch2Menu", are local to "setup_menu", so they don't have valid addresses after setup_menu returns. It's been years since I paid this any attention so I can't recall off the top of my head how this works...

7 years, 4 months ago.

Your problem is that all the Menu variables are local to setup_menu and so are on the stack and deleted once the procedure returns. This means that the object pointed to by active_menu is not valid. When all the code is in main then the local variables never go out of scope and so remain valid while the program run.

While there are many possible solutions here are two solutions of the more obvious ones:

  • Declare the Menu variables globally (outside a procedure or class) and then use a procedure to add the menu items themselves.
  • Turn setup_menu into a function that returns a pointer the the setup menu and use new to create the Menu instances on the heap. Creating them one the heap will ensure that the objects remain valid after the function has returned.

Hope this helps.