I'm trying to create a series of nested menus using pure ncurses in C++. If I create a menu and post it in main(), it works fine. But if I take the same code and put it in a function that returns a MENU*, it doesn't work at all. Am I missing something?
Code that works:
int main()
{
/*
* snipped out the curses startup code
*/
vector<char*> options;
options.push_back("List");
options.push_back("Add");
options.push_back("Delete");
options.push_back("Exit");
vector<ITEM*> menu_items(options.size());
for (int i = 0; i < options.size(); i++)
menu_items[i] = new_item(options[i], NULL);
MENU *options_menu;
options_menu = new_menu(&menu_items[0]);
set_menu_win(options_menu, main_window);
set_menu_sub(options_menu, derwin(main_window, 6, 20, 3, 3));
set_menu_mark(options_menu, ">");
refresh();
post_menu(options_menu); // this works fine
wrefresh(main_window);
/*
* snipped out the rest of the stuff
*/
}
Code that doesn't work:
MENU *make_menu()
{
/*
* same as code in previous main()
*/
return options_menu;
}
int main()
{
/*
* snip
*/
MENU *options_menu = make_menu();
refresh();
post_menu(options_menu); // this doesn't do anything
wrefresh(main_window);
/*
* snip
*/
}
I'll answer this for future searchers. It turns out that new_menu takes a pointer to an ITEM list and hangs onto it. If the ITEM list is on the stack of a function, it'll get deleted when the function returns, making the ITEM list invalid.
The solution to this problem is to create the ITEM list on the heap, either via new
in C++, or using malloc
(remember to delete
or free
!). Another option is to wrap the MENU in a class and keep the ITEM list as a member variable.
The simplest solution is to just make the MENU (or ITEM list) global.