简体   繁体   中英

GNU readline: enormous memory leak

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)

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. 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM