Рассмотрим следующий фрагмент:
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
int main() {
for (;;) {
char *buf = readline(">>> ");
if (!buf)
break;
free(buf);
}
}
Компиляция с -lreadline
, выполнение программы под valgrind
и ввод некоторых строк приводят к огромной утечке памяти, на моей системе приговор valgrinds выглядит примерно так:
==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
Запуск с --show-leak-kinds=all
приводит к чему-то вроде этого (всего несколько сотен строк, я покажу только начало):
==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)
Теперь, несмотря на то, что память не потеряна, тот факт, что readline просто не освобождает огромные куски памяти до выхода из программы, кажется мне совершенно абсурдным. Я что-то пропустил? Должен ли я вручную вызывать некоторые плохо документированные функции очистки? Это ошибка? Это происходит в каждой системе?
Похоже, что в Интернете возникает несколько похожих проблем, но я был удивлен, увидев, что это происходит даже в простейшем случае использования.
РЕДАКТИРОВАТЬ: потому что было много обсуждений, я поясню немного: ответ Бруно, конечно, правильный, это не утечка памяти в традиционном смысле и почти на всех платформах это не будет иметь никакого значения (я включил тег Linux, который был ошибкой, я удалил его сейчас), но я все же хотел бы знать, действительно ли это сделано намеренно или произойдет ли это потому, что память освобождается только после того, как valgrind выдаст свою статистику, и если есть какой-либо способ обойти это (или, по крайней мере, заставить valgrind игнорировать его, чтобы он не скрывал пропущенные вызовы free
в остальной части моего кода)