Stack Exchange
cannot fix memory leak in ncurses
I have an ncurses program that sets two SCREEN's with setterm.
I believe I am not finishing them correctly, since I get bunch of valgrind errors (see below).
Any idea what's wrong??
Thanks!!
#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 reports:
==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)


It's an 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.

Following up from comments: the issue here was that depending on the compile-time configuration, ncurses maintains either a list of windows per screen, or a global list of windows (across all screens).  In the latter, it was discarding the list when creating a new screen.  Fixed now:
20170325
        + fix a memory leak in the window-list when creating multiple screens
          (reports by Andres Martinelli, Debian #783486).


The way I finished both SCREEN with endwin() is ok? or something is missing? thanks.

endwin doesn't free memory.  You would get some reduction using delscreen (called after endwin).  Even with that, there's some low-level memory which never gets freed.

but if i add the delscreen after both endwin.. now i get definitely lost and indirectly lost errors, rather than possiblel lost errors..

yes... that's because valgrind can see the remaining pieces better.  There's debugging code (for the library, if you configure and compile it), which attempts to free everything, but that's not part of a normal package since some of the free's interfere with the library's operation.

you mean building ncurses with --disable-leaks?
I did just that, and also used _nc_free_and_exit().
Thats what you are suggesting or something else? Thanks!

since i have using ncurses and debugging ncurses for years without a problem until now that i started to use newterm.. I believe this is what im getting.. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=783486

I see (something to followup on).

This is fixed now with latest patch! No memory leak shown. Thanks.

no problem (if I answered the question well enough, you might accept it)

I just pushed an edit through for the link as it was/is malformed. Just fwiw.
