Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GNU readline: enormous memory leak

Tags:

c

gnu

readline

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)

like image 493
Peter Avatar asked Mar 16 '19 11:03

Peter


People also ask

Do Memory leaks cause permanent damage?

Physical or permanent damage does not happen from memory leaks. Memory leaks are strictly a software issue, causing performance to slow down among applications within a given system.

Which condition causes memory leak?

Memory leaks are a common error in programming, especially when using languages that have no built in automatic garbage collection, such as C and C++. Typically, a memory leak occurs because dynamically allocated memory has become unreachable.

Are memory leaks OK?

Disadvantage with memory leakage: If a program has memory leaks, then its memory usage is satirically increasing since all systems have limited amount of memory and memory is costly. Hence it will create problems.

What causes memory leak in Linux?

A memory leak occurs when memory is allocated but not freed when it is no longer needed. Leaks can obviously be caused by a malloc() without a corresponding free() , but leaks can also be inadvertently caused if a pointer to dynamically allocated memory is deleted, lost, or overwritten.


1 Answers

GNU readline: enormous memory leak

==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

There is no memory leak

==7651==    still reachable: 213,455 bytes in 217 blocks
==7651==         suppressed: 0 bytes in 0 blocks
...

A reachable memory is not a memory leak

==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)
...

getline used memory and still references it, do not forget it manages a history, and the history can be freed calling void rl_clear_history (void), add that function call in your program and redo a test

Function: void rl_clear_history (void)
  Clear the history list by deleting all of the entries, in the same
  manner as the History library's clear_history() function. This differs
  from clear_history because it frees private data Readline saves in the history list.
like image 90
bruno Avatar answered Oct 16 '22 20:10

bruno