无法修复 ncurses 中的内存泄漏
cannot fix memory leak in ncurses
我有一个使用 setterm 设置两个屏幕的 ncurses 程序。
我相信我没有正确地完成它们,因为我遇到了一堆 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)
这是一个 FAQ:
Perhaps you used a tool such as dmalloc or valgrind to check for memory leaks. It will normally report a lot of memory still in use. That is normal.
The ncurses configure script has an option, --disable-leaks, which you can use to continue the analysis. It tells ncurses to free memory if possible. However, most of the in-use memory is "permanent".
Any implementation of curses must not free the memory associated with a screen, since (even after calling endwin()), it must be available for use in the next call to refresh(). There are also chunks of memory held for performance reasons. That makes it hard to analyze curses applications for memory leaks. To work around this, build a debugging version of the ncurses library which frees those chunks which it can, and provides the _nc_free_and_exit() function to free the remainder on exit. The ncurses utility and test programs use this feature, e.g., via the ExitProgram() macro.
根据评论跟进:这里的问题是,根据编译时配置,ncurses 维护每个屏幕的 windows 列表,或 windows 的全局列表(在所有屏幕)。在后者中,它在创建新屏幕时丢弃了列表。 Fixed now:
20170325
+ fix a memory leak in the window-list when creating multiple screens
(reports by Andres Martinelli, Debian #783486).
我有一个使用 setterm 设置两个屏幕的 ncurses 程序。 我相信我没有正确地完成它们,因为我遇到了一堆 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)
这是一个 FAQ:
Perhaps you used a tool such as dmalloc or valgrind to check for memory leaks. It will normally report a lot of memory still in use. That is normal.
The ncurses configure script has an option, --disable-leaks, which you can use to continue the analysis. It tells ncurses to free memory if possible. However, most of the in-use memory is "permanent".
Any implementation of curses must not free the memory associated with a screen, since (even after calling endwin()), it must be available for use in the next call to refresh(). There are also chunks of memory held for performance reasons. That makes it hard to analyze curses applications for memory leaks. To work around this, build a debugging version of the ncurses library which frees those chunks which it can, and provides the _nc_free_and_exit() function to free the remainder on exit. The ncurses utility and test programs use this feature, e.g., via the ExitProgram() macro.
根据评论跟进:这里的问题是,根据编译时配置,ncurses 维护每个屏幕的 windows 列表,或 windows 的全局列表(在所有屏幕)。在后者中,它在创建新屏幕时丢弃了列表。 Fixed now:
20170325
+ fix a memory leak in the window-list when creating multiple screens
(reports by Andres Martinelli, Debian #783486).