bug-ncurses
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A Valgrind-observant ncurses


From: G. Branden Robinson
Subject: Re: A Valgrind-observant ncurses
Date: Thu, 20 Jun 2024 17:06:43 -0500

Hi Thomas,

At 2024-06-20T15:47:38-0400, Thomas Dickey wrote:
> On Thu, Jun 20, 2024 at 01:06:54PM -0400, Bill Gray wrote:
> > static char buffer[80];
> > 
> >    What I meant was that you have a buffer that is allocated when
> >    printw() is first called,  and possibly resized if it needs to be
> >    made larger.  On the first call to printw(),  it might allocate
> >    an 80 byte buffer,  figuring that'll be big enough 99% of the
> >    time.   Then,  when it encounters a printw() that requires 200
> >    bytes,  the buffer is re-allocated to be (say) 300 bytes.
> >    Subsequent calls may exceed even that limit,  and cause the
> >    buffer to be re-re-allocated to be still larger.
> > 
> >    Ideally,  the buffer is then freed when endwin() or delscreen()
> >    is called.  Except that doesn't happen here.
> 
> It shouldn't, because curses guarantees that you can do a refresh
> after endwin and get the screen contents as they were.

Doesn't printw() update curscr (via waddstr()), so by the time of the
next curses function call, it would no longer require this buffer?

Testing my own hypothesis:

$ git di ncurses
diff --git a/ncurses/base/lib_printw.c b/ncurses/base/lib_printw.c
index d901b727a..2cf87f887 100644
--- a/ncurses/base/lib_printw.c
+++ b/ncurses/base/lib_printw.c
@@ -162,6 +162,7 @@ vw_printw(WINDOW *win, const char *fmt, va_list argp)
     buf = NCURSES_SP_NAME(_nc_printf_string) (NCURSES_SP_ARGx fmt, argp);
     if (buf != 0) {
        code = waddstr(win, buf);
+       free(buf);
     }
     returnCode(code);
 }

Well, nope.  ./test/bs silently dies with status 1 if I add that line.

I'm a little puzzled as to why.

Here's the backtrace:

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff7d73537 in __GI_abort () at abort.c:79
#2  0x00007ffff7dcb3e8 in __libc_message (action=action@entry=do_abort, 
fmt=fmt@entry=0x7ffff7ee9390 "%s\n")
    at ../sysdeps/posix/libc_fatal.c:155
#3  0x00007ffff7dd26da in malloc_printerr (str=str@entry=0x7ffff7eeb730 "double 
free or corruption (top)")
    at malloc.c:5347
#4  0x00007ffff7dd3ce4 in _int_free (av=0x7ffff7f1fb80 <main_arena>, 
p=0x5555555ceb80, have_lock=<optimized out>)
    at malloc.c:4309
#5  0x00007ffff7f732ef in vw_printw (win=0x5555555ab7e0,
    fmt=0x55555555a0c0 "To position your ships: move the cursor to a spot, 
then", argp=0x7fffffffda70)
    at ../ncurses/./base/lib_printw.c:165
#6  0x00007ffff7f73122 in mvprintw (y=15, x=0,
    fmt=0x55555555a0c0 "To position your ships: move the cursor to a spot, 
then")
    at ../ncurses/./base/lib_printw.c:104
#7  0x0000555555556f7c in initgame () at ../test/bs.c:411
#8  0x000055555555977e in main (argc=1, argv=0x7fffffffdcb8) at 
../test/bs.c:1251
##(gdb) f 5
#5  0x00007ffff7f732ef in vw_printw (win=0x5555555ab7e0,
    fmt=0x55555555a0c0 "To position your ships: move the cursor to a spot, 
then", argp=0x7fffffffda70)
    at ../ncurses/./base/lib_printw.c:165
165             free(buf);

The previous function call in this frame is `waddstr()`, which
eventually lands in `waddch_nosync()`, which neither allocates nor frees
memory.  So the faulure is a mystery to me.

Regards,
Branden

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]