Consider the following snippet:
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
int main() {
for (;;) {
char *buf = readline(">>> ");
if (!buf)
break;
free(buf);
}
}
Compiling with -lreadline
, executing the program under valgrind
and inputting some lines result in an enormous memory leak, on my system valgrinds verdict looks something like this:
==7651== LEAK SUMMARY:
==7651== definitely lost: 0 bytes in 0 blocks
==7651== indirectly lost: 0 bytes in 0 blocks
==7651== possibly lost: 0 bytes in 0 blocks
==7651== still reachable: 213,455 bytes in 217 blocks
==7651== suppressed: 0 bytes in 0 blocks
Running with --show-leak-kinds=all
results something like this (the whole thing is several hundred lines long, I'll only show the beginning):
==7693== 5 bytes in 1 blocks are still reachable in loss record 1 of 57
==7693== at 0x483777F: malloc (vg_replace_malloc.c:299)
==7693== by 0x48CE409: xmalloc (in /usr/lib/libreadline.so.8.0)
==7693== by 0x48A72E6: rl_set_prompt (in /usr/lib/libreadline.so.8.0)
==7693== by 0x48A87E6: readline (in /usr/lib/libreadline.so.8.0)
==7693== by 0x10915C: main (in /home/.../a.out)
==7693==
==7693== 5 bytes in 1 blocks are still reachable in loss record 2 of 57
==7693== at 0x483777F: malloc (vg_replace_malloc.c:299)
==7693== by 0x48CE409: xmalloc (in /usr/lib/libreadline.so.8.0)
==7693== by 0x48B95BC: ??? (in /usr/lib/libreadline.so.8.0)
==7693== by 0x48B9D25: rl_expand_prompt (in /usr/lib/libreadline.so.8.0)
==7693== by 0x48A7309: rl_set_prompt (in /usr/lib/libreadline.so.8.0)
==7693== by 0x48A87E6: readline (in /usr/lib/libreadline.so.8.0)
==7693== by 0x10915C: main (in /home/.../a.out)
==7693==
==7693== 8 bytes in 1 blocks are still reachable in loss record 3 of 57
==7693== at 0x483777F: malloc (vg_replace_malloc.c:299)
==7693== by 0x496C49E: strdup (in /usr/lib/libc-2.28.so)
==7693== by 0x4AEEDCD: _nc_trim_sgr0 (in /usr/lib/libncursesw.so.6.1)
==7693== by 0x4AE7EA2: tgetent_sp (in /usr/lib/libncursesw.so.6.1)
==7693== by 0x48C39BC: _rl_init_terminal_io (in /usr/lib/libreadline.so.8.0)
==7693== by 0x48A851C: rl_initialize (in /usr/lib/libreadline.so.8.0)
==7693== by 0x48A87EC: readline (in /usr/lib/libreadline.so.8.0)
==7693== by 0x10915C: main (in /home/.../a.out)
Now despite the fact that the memory is not lost, the fact that readline simply does not free huge chunks of memory before program exit seems completely absurd to me. Am I missing something? Should I manually call some poorly documented cleanup functions? Is this a bug? Does this occur on every system?
There seem to be several similar issues floating around the Internet but I was surprised to see that this happens even in the simplest possible use case.
EDIT: because there has been a lot of discussion I will clarify a little: bruno's answer is of course correct, it's not a memory leak in the traditional sense and on almost all platforms it won't matter at all (I included the Linux tag, which was a mistake, I have removed it now), but I'd still like to know if this is really intentional or if happens because the memory is freed only after valgrind produces its statistics and if there is any way to get around this (or at the very least make valgrind ignore it so that it does not obscure missing free
calls in the rest of my code)