Valgrind使用适当的free()和end()后,显示ncurses命令的内存泄漏

des*_*vel 1 c c++ curses memory-leaks ncurses

我有一个正在编写的程序可以更好地理解ncurses,当我将其推送通过时valgrind,它会输出与ncurses命令相关的许多泄漏。但是,我仅使用stdscrendwin()在末尾调用main()。我通过使用menu.h设置了用户选项,并在最后使用了free_item和free_menu:

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;
}
Run Code Online (Sandbox Code Playgroud)

但是,valgrind仍然给了我很多这样的东西:

==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)
Run Code Online (Sandbox Code Playgroud)

尽管它并没有显示太多泄漏,但仍然让我觉得当我遵守规则时我做错了什么。

Tho*_*key 5

在ncurses 内存泄漏常见问题测试中对此进行了讨论:

也许您使用了dmalloc或valgrind之类的工具来检查内存泄漏。它通常会报告仍在使用大量内存。那是正常的。

ncurses配置脚本​​具有--disable-leaks选项,您可以使用该选项继续进行分析。如果可能,它告诉ncurses释放内存。但是,大多数使用中的内存是“永久”的。

curses的任何实现都不得释放与屏幕关联的内存,因为(即使在调用endwin()之后),它也必须可用于下一次对refresh()的调用。也出于性能原因保留了大块内存。这使得很难分析curses应用程序的内存泄漏。要解决此问题,请构建ncurses库的调试版本,该版本将释放可能释放的那些块,并提供_nc_free_and_exit()在退出时释放其余部分的功能。ncurses实用程序和测试程序使用此功能,例如通过ExitProgram()宏。