【问题标题】:cannot fix memory leak in ncurses无法修复 ncurses 中的内存泄漏
【发布时间】:2017-08-11 17:30:05
【问题描述】:

我有一个 ncurses 程序,它使用 setterm 设置两个 SCREEN。 我相信我没有正确完成它们,因为我遇到了一堆 valgrind 错误(见下文)。 知道有什么问题吗? 谢谢!!

#include <ncurses.h>
SCREEN * sstderr;
SCREEN * sstdout;
int main() {
    sstderr = newterm(NULL, stderr, NULL);
    noecho();
    sstdout = newterm(NULL, stdout, stdin);
    set_term(sstdout);

    mvaddstr(0, 0, "algo\n");
    clrtobot();
    getch();
    refresh();

    set_term(sstdout);
    endwin();
    set_term(sstderr);
    endwin();
    return 0;
}

Valgrind 报告:

==10283== Memcheck, a memory error detector
==10283== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==10283== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==10283== Command: ./a.out
==10283== Parent PID: 669
==10283== 
==10283== 
==10283== HEAP SUMMARY:
==10283==     in use at exit: 1,225,551 bytes in 313 blocks
==10283==   total heap usage: 328 allocs, 15 frees, 1,242,329 bytes allocated
==10283== 
==10283== 296 bytes in 1 blocks are possibly lost in loss record 27 of 55
==10283==    at 0x4C2CA40: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10283==    by 0x4E5B88D: _nc_makenew_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5BB2D: newwin_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5FBC5: _nc_setupscreen_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5B17E: newterm_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x400932: main (in /home/mongo/a.out)
==10283== 
==10283== 296 bytes in 1 blocks are possibly lost in loss record 28 of 55
==10283==    at 0x4C2CA40: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10283==    by 0x4E5B88D: _nc_makenew_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5BB2D: newwin_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5FBEA: _nc_setupscreen_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5B17E: newterm_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x400932: main (in /home/mongo/a.out)
==10283== 
==10283== 296 bytes in 1 blocks are possibly lost in loss record 29 of 55
==10283==    at 0x4C2CA40: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10283==    by 0x4E5B88D: _nc_makenew_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5BB2D: newwin_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5FD50: _nc_setupscreen_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5B17E: newterm_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x400932: main (in /home/mongo/a.out)
==10283== 
==10283== 704 bytes in 1 blocks are possibly lost in loss record 37 of 55
==10283==    at 0x4C2CA40: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10283==    by 0x4E5B8AF: _nc_makenew_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5BB2D: newwin_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5FBC5: _nc_setupscreen_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5B17E: newterm_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x400932: main (in /home/mongo/a.out)
==10283== 
==10283== 704 bytes in 1 blocks are possibly lost in loss record 38 of 55
==10283==    at 0x4C2CA40: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10283==    by 0x4E5B8AF: _nc_makenew_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5BB2D: newwin_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5FBEA: _nc_setupscreen_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5B17E: newterm_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x400932: main (in /home/mongo/a.out)
==10283== 
==10283== 704 bytes in 1 blocks are possibly lost in loss record 39 of 55
==10283==    at 0x4C2CA40: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10283==    by 0x4E5B8AF: _nc_makenew_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5BB2D: newwin_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5FD50: _nc_setupscreen_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5B17E: newterm_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x400932: main (in /home/mongo/a.out)
==10283== 
==10283== 197,120 bytes in 44 blocks are possibly lost in loss record 53 of 55
==10283==    at 0x4C2CA40: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10283==    by 0x4E5BB83: newwin_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5FBC5: _nc_setupscreen_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5B17E: newterm_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x400932: main (in /home/mongo/a.out)
==10283== 
==10283== 197,120 bytes in 44 blocks are possibly lost in loss record 54 of 55
==10283==    at 0x4C2CA40: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10283==    by 0x4E5BB83: newwin_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5FBEA: _nc_setupscreen_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5B17E: newterm_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x400932: main (in /home/mongo/a.out)
==10283== 
==10283== 197,120 bytes in 44 blocks are possibly lost in loss record 55 of 55
==10283==    at 0x4C2CA40: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10283==    by 0x4E5BB83: newwin_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5FD50: _nc_setupscreen_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x4E5B17E: newterm_sp (in /usr/lib/libncursesw.so.6.0)
==10283==    by 0x400932: main (in /home/mongo/a.out)
==10283== 
==10283== LEAK SUMMARY:
==10283==    definitely lost: 0 bytes in 0 blocks
==10283==    indirectly lost: 0 bytes in 0 blocks
==10283==      possibly lost: 594,360 bytes in 138 blocks
==10283==    still reachable: 631,191 bytes in 175 blocks
==10283==         suppressed: 0 bytes in 0 blocks
==10283== Reachable blocks (those to which a pointer was found) are not shown.
==10283== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==10283== 
==10283== For counts of detected and suppressed errors, rerun with: -v
==10283== ERROR SUMMARY: 9 errors from 9 contexts (suppressed: 0 from 0)

【问题讨论】:

    标签: c ncurses


    【解决方案1】:

    这是一个FAQ

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

    ncurses 配置脚本有一个选项 --disable-leaks,您可以使用它来继续分析。如果可能,它会告诉 ncurses 释放内存。但是,大部分正在使用的内存是“永久的”。

    curses 的任何实现都不能释放与屏幕相关的内存,因为(即使在调用 endwin() 之后),它必须在下一次调用 refresh() 时可用。出于性能原因,还有一些内存块。这使得分析 curses 应用程序的内存泄漏变得困难。为了解决这个问题,构建 ncurses 库的调试版本,它可以释放那些它可以释放的块,并提供 _nc_free_and_exit() 函数以在退出时释放剩余部分。 ncurses 实用程序和测试程序使用此功能,例如,通过 ExitProgram() 宏。

    从 cmets 跟进:这里的问题是,根据编译时配置,ncurses 维护每个屏幕的窗口列表或全局窗口列表(跨所有屏幕)。在后者中,它在创建新屏幕时丢弃了列表。 Fixed now:

    20170325
            + fix a memory leak in the window-list when creating multiple screens
              (reports by Andres Martinelli, Debian #783486).
    

    【讨论】:

    • 我用 endwin() 完成两个 SCREEN 的方式好吗?还是缺少什​​么?谢谢。
    • endwin 不会释放内存。使用delscreen(称为after endwin)会有所减少。即使这样,也有一些低级内存永远不会被释放。
    • 但是如果我在两个 endwin 之后添加 delscreen.. 现在我肯定会丢失和间接丢失错误,而不是可能丢失的错误..
    • 是的......那是因为 valgrind 可以更好地看到剩余的部分。有调试代码(对于库,如果你配置和编译它),它试图释放所有东西,但这不是正常包的一部分,因为一些释放会干扰库的操作。
    • 您的意思是使用--disable-leaks 构建ncurses?我就是这样做的,并且还使用了_nc_free_and_exit()。那是你的建议还是别的什么?谢谢!
    猜你喜欢
    • 1970-01-01
    • 2011-08-13
    • 1970-01-01
    • 2012-01-12
    • 2018-02-23
    • 2021-09-27
    • 2013-07-29
    • 2017-07-29
    相关资源
    最近更新 更多