Mik*_*ike 5 c valgrind ncurses calloc
以下代码是NCURSES菜单库中的一个示例。我不确定代码有什么问题,但 valgrind 报告了一些问题。有任何想法吗...
==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
Run Code Online (Sandbox Code Playgroud)
源代码:
#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();
}
Run Code Online (Sandbox Code Playgroud)
根据NCURSES 编程指南,使用菜单库需要以下步骤:
初始化诅咒 使用 new_item() 创建项目。您可以指定项目的名称和描述。 通过指定要附加的项目,使用 new_menu() 创建菜单。 使用 menu_post() 发布菜单并刷新屏幕。 使用循环处理用户请求,并使用 menu_driver 对菜单进行必要的更新。 使用 menu_unpost() 取消发布菜单 通过 free_menu() 释放分配给菜单的内存 使用 free_item() 释放分配给项目的内存 结束诅咒
从你的代码中我可以看出:
my_items永远不会被释放。这肯定是泄漏。正如@lh3所说,使用该-g选项进行编译将使Valgrind给出丢失内存的行号。
编辑(响应您的评论):my_items是动态分配的指向动态创建的菜单项的指针数组。换句话说,你有一个动态内存块,它包含一堆指向一堆动态分配的 ncurses 结构(菜单项)的指针。因此,完成后要进行清理,您需要释放每个动态分配的 ncurses 结构,然后需要释放保存指向这些结构的指针的内存块。
换句话说,每个calloc或都malloc需要一个free,每个都new_item需要一个free_item,依此类推。
for (i = 0; i < n_choices; ++i) {
free_item(my_items[i]);
}
free(my_items);
Run Code Online (Sandbox Code Playgroud)