[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 19:18:28 -0500 |
Hi Bill,
At 2024-06-20T19:49:54-0400, Bill Gray wrote:
> On 6/20/24 18:06, G. Branden Robinson wrote:
> > Doesn't printw() update curscr (via waddstr()), so by the time of
> > the next curses function call, it would no longer require this
> > buffer?
>
> It looks as if the buffer is re-used each time you call printw().
> Call it once, and the buffer is allocated; call it again, and
> it's re-used (if it's already large enough) or resized (if it
> isn't). This logic is all encapsulated in 'safe_sprintf.c', where
> the buffer is 'my_buffer' and its size is 'my_length'.
Aha. I hadn't even looked at that file before. It illuminates much.
> With your modification, the buffer is allocated and used on the
> first call, but then immediately freed. On the second call, we
> attempt to use the (now freed) pointer, or to resize it. Either
> way, we'll crash.
Agreed. It occurred to me that bad things would happen if multiple
threads called printw() (or anything that eventually called
_nc_printf_string()). You're not supposed to do that -- at least not
without wrapping the calls with use_window(), I think.
The ncurses_threads(3x) man page could perhaps offer more explicit
multithreaded ncurses application design advice. Either:
1. Have one worker thread per {screen,window}, depending on which data
structure the (n)curses function affects.
2. Wrap window/screen-affecting (n)curses calls in
use_window() or use_screen() as appropriate.
That's my understanding at this moment. Could be wrong.
I'm also curious to know if ncurses use the "many readers XOR one
writer" model of mutual exclusion, or the simpler "one reader/writer at
any time" approach. (Someone can tell me, or eventually I'll comprehend
the code.)
> I think what has to happen instead is that, at either endwin() or
> delscreen(), we call _nc_printf_string( NULL, NULL). If you look
> down near the end of that function, you can see that those
> arguments are the magic values to cause 'my_buffer' to be freed,
> set to NULL, and 'my_length' set to zero. If you _do_ restart
> curses, the buffer may get allocated again.
A nifty idea.
> As Thomas notes, endwin() is limited in what it can free, because
> you may restart curses. To get Valgrind to report only five or six
> unfreed allocations, you have to use newterm() and, at shutdown,
> pass the resulting SCREEN pointer to delscreen().
If Thomas doesn't do this, I may, to get some experience with a
--disable-leaks build.
I'm curious to hear what he thinks of your idea above.
Regards,
Branden
signature.asc
Description: PGP signature
- Re: A Valgrind-observant ncurses, (continued)
- Re: A Valgrind-observant ncurses, Thomas Dickey, 2024/06/20
- Re: A Valgrind-observant ncurses, Michael D. Setzer II, 2024/06/20
- Re: A Valgrind-observant ncurses, Thomas Dickey, 2024/06/22
- Re: A Valgrind-observant ncurses, Steve Litt, 2024/06/23
- Re: Ctrl-L cleaning the screen, Thomas Dickey, 2024/06/23
- Re: A Valgrind-observant ncurses, G. Branden Robinson, 2024/06/20
- Re: A Valgrind-observant ncurses, Bill Gray, 2024/06/20
- Re: A Valgrind-observant ncurses,
G. Branden Robinson <=
- Re: A Valgrind-observant ncurses, Thomas Dickey, 2024/06/21
Re: A Valgrind-observant ncurses, Thomas Dickey, 2024/06/20