问题
I have a program I'm writing to better understand ncurses, and when I push it through valgrind
, it outputs many leaks associated with ncurses commands.
However, I only use stdscr
, and call endwin()
at the end of main()
. I have user options set by using menu.h, and use free_item and free_menu at the end:
menuChoice(WINDOW* scr, std::vector<std::string> *choices,
std::string desc)
{
//create the menu and the item pointer vector
MENU* my_menu;
std::vector<ITEM*> my_items;
ITEM* cur = NULL;
for (int x = 0; x < choices->size(); x++)
{
//populate the items vector with the string data in choices
my_items.push_back(new_item(choices->at(x).c_str(), NULL));
}
//pushback a null item
my_items.push_back((ITEM*)NULL);
//create the menu and attach the items
my_menu = new_menu((ITEM**)my_items.data());
//print the desc and post the menu
mvwprintw(scr, LINES - 3, 0, "%s\n", desc.c_str());
post_menu(my_menu);
wrefresh(scr);
int c = 0;
while((c = wgetch(scr)) != '\n')
{ switch(c)
{ case KEY_DOWN:
menu_driver(my_menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(my_menu, REQ_UP_ITEM);
break;
}
}
cur = current_item(my_menu);
int toReturn;
toReturn = boost::lexical_cast<int>((char*) item_name(cur));
unpost_menu(my_menu);
for (int x = 0; x < my_items.size(); x++)
{
free_item(my_items[x]);
}
free_menu(my_menu);
return toReturn;
}
However, valgrind
still gives me lots of this:
==25266== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==25266== by 0x405F2F3: _nc_hash_map (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x405E606: _nc_scroll_optimize (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x4075FF1: doupdate (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x406B02E: wrefresh (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x4064AAF: ??? (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x4064C46: _nc_wgetch (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x40658B9: wgetch (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x804B309: blackjack::menuChoice(_win_st*, std::vector<std::string, std::allocator<std::string> >*, std::string) (blackjack.cpp:555)
==25266== by 0x804AF66: blackjack::prefScreen(_win_st*) (blackjack.cpp:521)
==25266== by 0x8049BFF: blackjack::blackjack(_win_st*) (blackjack.cpp:21)
==25266== by 0x8050118: blackjack_routine(_win_st*) (main.cpp:50)
==25266==
==25266== 1,900 bytes in 1 blocks are still reachable in loss record 44 of 49
==25266== at 0x402C324: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==25266== by 0x4088068: _nc_doalloc (in /lib/i386-linux-gnu/libtinfo.so.5.9)
==25266== by 0x4090076: _nc_read_termtype (in /lib/i386-linux-gnu/libtinfo.so.5.9)
==25266== by 0x40903EB: _nc_read_file_entry (in /lib/i386-linux-gnu/libtinfo.so.5.9)
==25266== by 0x4090578: _nc_read_entry (in /lib/i386-linux-gnu/libtinfo.so.5.9)
==25266== by 0x408A5E4: _nc_setup_tinfo (in /lib/i386-linux-gnu/libtinfo.so.5.9)
==25266== by 0x408A95B: _nc_setupterm (in /lib/i386-linux-gnu/libtinfo.so.5.9)
==25266== by 0x4069580: newterm (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x4066013: initscr (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x80500C2: main (main.cpp:36)
==25266==
==25266== 2,836 bytes in 1 blocks are still reachable in loss record 45 of 49
==25266== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==25266== by 0x408807F: _nc_doalloc (in /lib/i386-linux-gnu/libtinfo.so.5.9)
==25266== by 0x406F026: _nc_printf_string (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x406AB22: vwprintw (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x406AC68: mvwprintw (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x804B2A3: blackjack::menuChoice(_win_st*, std::vector<std::string, std::allocator<std::string> >*, std::string) (blackjack.cpp:550)
==25266== by 0x804AF66: blackjack::prefScreen(_win_st*) (blackjack.cpp:521)
==25266== by 0x8049BFF: blackjack::blackjack(_win_st*) (blackjack.cpp:21)
==25266== by 0x8050118: blackjack_routine(_win_st*) (main.cpp:50)
==25266== by 0x80500F3: main (main.cpp:41)
==25266==
==25266== 3,182 bytes in 1 blocks are still reachable in loss record 46 of 49
==25266== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==25266== by 0x406C0CF: _nc_setupscreen (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x40695CE: newterm (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x4066013: initscr (in /lib/i386-linux-gnu/libncurses.so.5.9)
==25266== by 0x80500C2: main (main.cpp:36)
While it doesn't show much leakage, it still makes me think I've done something wrong when I feel like I've followed the rules.
回答1:
That is discussed in the ncurses FAQ Testing for Memory Leaks:
Perhaps you used a tool such as dmalloc or valgrind to check for memory leaks. It will normally report a lot of memory still in use. That is normal.
The ncurses configure script has an option, --disable-leaks, which you can use to continue the analysis. It tells ncurses to free memory if possible. However, most of the in-use memory is "permanent".
Any implementation of curses must not free the memory associated with a screen, since (even after calling endwin()), it must be available for use in the next call to refresh(). There are also chunks of memory held for performance reasons. That makes it hard to analyze curses applications for memory leaks. To work around this, build a debugging version of the ncurses library which frees those chunks which it can, and provides the
_nc_free_and_exit()
function to free the remainder on exit. The ncurses utility and test programs use this feature, e.g., via theExitProgram()
macro.
来源:https://stackoverflow.com/questions/32410125/valgrind-shows-memory-leaks-from-ncurses-commands-after-using-appropriate-free