调用 calloc - 内存泄漏 valgrind
以下代码是 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
源代码:
#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();
}
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();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
根据 NCURSES 编程指南,使用菜单库需要以下内容步骤:
从我从你的代码中可以看出:
my_items
指针数组永远不会被释放。这肯定是泄漏。正如 @lh3 所说,使用
-g
选项进行编译将使 Valgrind 给出丢失内存的行号。编辑(响应您的评论):
my_items
是动态分配的指向动态创建的菜单项的指针数组。换句话说,你有一个动态内存块,它包含一堆指向一堆动态分配的 ncurses 结构(菜单项)的指针。因此,完成后要进行清理,您需要释放每个动态分配的 ncurses 结构,然后需要释放保存指向这些结构的指针的内存块。换句话说,每个
calloc
或malloc
都需要一个free
,每个new_item
需要一个free_item
代码>,等等。According to the NCURSES Programming Howto, using the menus library requires the following steps:
From what I can tell from your code:
my_items
array of pointers is never freed. This is certainly a leak.As @lh3 said, compiling with the
-g
option will let Valgrind give the line number of lost memory.Edit (in response to your comment):
my_items
is 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
calloc
ormalloc
needs afree
, everynew_item
needs afree_item
, and so on.Valgrind 需要注意的事项(Valgrind 用户的邮件列表经常出现) ):
这只是引用在退出时仍可在
main()
中访问的块,这些块(在任何现代内核下)无论如何都会被操作系统回收。虽然在调用退出之前显式地
free()
每个分配的块是一个很好的做法,但这在技术上并不是泄漏内存,因为在退出时仍然可以到达它。正如 Josh Kelly 建议的那样,重点关注直接、间接和可能丢失的块。这只是对已经指出可能的泄漏来源的答案的补充。
Something to note with Valgrind (this comes up on the Valgrind user's mailing list often):
This is just referencing blocks that were still reachable in
main()
at exit, which (under any modern kernel) would just be reclaimed by the OS anyway.While its good practice to explicitly
free()
every single allocated block before exit is called, this is nottechnically
leaked memory, since it still could be reached at the time of exit.Focus on directly, indirectly and possibly lost blocks as Josh Kelly has suggested. This is just a supplement to the answers that have already pointed out the likely sources of leaks.
尝试使用 --leak-check=full 运行 valgrind 吧?
try running valgrind with --leak-check=full maybe?