The following code is an example from the NCURSES menu library. I’m not sure what could be wrong with the code, but valgrind reports some problems. Any ideas…
==4803== 1,049 (72 direct, 977 indirect) bytes in 1 blocks are definitely lost in loss record 25 of 36
==4803== at 0x4C24477: calloc (vg_replace_malloc.c:418)
==4803== by 0x400E93: main (in /home/gerardoj/a.out)
==4803==
==4803== LEAK SUMMARY:
==4803== definitely lost: 72 bytes in 1 blocks
==4803== indirectly lost: 977 bytes in 10 blocks
==4803== possibly lost: 0 bytes in 0 blocks
==4803== still reachable: 64,942 bytes in 262 blocks
Source code:
#include <curses.h>
#include <menu.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define CTRLD 4
char *choices[] = {
"Choice 1",
"Choice 2",
"Choice 3",
"Choice 4",
"Choice 5",
"Choice 6",
"Choice 7",
"Exit",
}
;
int main()
{
ITEM **my_items;
int c;
MENU *my_menu;
int n_choices, i;
ITEM *cur_item;
/* Initialize curses */
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
/* Initialize items */
n_choices = ARRAY_SIZE(choices);
my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));
for (i = 0; i < n_choices; ++i) {
my_items[i] = new_item(choices[i], choices[i]);
}
my_items[n_choices] = (ITEM *)NULL;
my_menu = new_menu((ITEM **)my_items);
/* Make the menu multi valued */
menu_opts_off(my_menu, O_ONEVALUE);
mvprintw(LINES - 3, 0, "Use <SPACE> to select or unselect an item.");
mvprintw(LINES - 2, 0, "<ENTER> to see presently selected items(F1 to Exit)");
post_menu(my_menu);
refresh();
while ((c = getch()) != KEY_F(1)) {
switch (c) {
case KEY_DOWN:
menu_driver(my_menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(my_menu, REQ_UP_ITEM);
break;
case ' ':
menu_driver(my_menu, REQ_TOGGLE_ITEM);
break;
case 10:
{
char temp[200];
ITEM **items;
items = menu_items(my_menu);
temp[0] = '\0';
for (i = 0; i < item_count(my_menu); ++i)
if(item_value(items[i]) == TRUE) {
strcat(temp, item_name(items[i]));
strcat(temp, " ");
}
move(20, 0);
clrtoeol();
mvprintw(20, 0, temp);
refresh();
}
break;
}
}
unpost_menu(menu);
free_item(my_items[0]);
free_item(my_items[1]);
free_item(my_items[2]);
free_item(my_items[3]);
free_item(my_items[4]);
free_item(my_items[5]);
free_item(my_items[6]);
free_item(my_items[7]);
free_menu(my_menu);
endwin();
}
According to the NCURSES Programming Howto, using the menus library requires the following steps:
From what I can tell from your code:
my_itemsarray of pointers is never freed. This is certainly a leak.As @lh3 said, compiling with the
-goption will let Valgrind give the line number of lost memory.Edit (in response to your comment):
my_itemsis a dynamically allocated array of pointers to dynamically created menu items. In other words, you have one block of dynamic memory, and it contains a bunch of pointers to a bunch of dynamically allocated ncurses structures (menu items). So, to clean up once you’re done, you need to free each of the dynamically allocated ncurses structures, and then you need to free the block of memory that held the pointers to those structures.In other words, every
callocormallocneeds afree, everynew_itemneeds afree_item, and so on.