请考虑以下代码段:
#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并没有在程序退出之前释放大量内存,这对我来说似乎是完全荒谬的。我想念什么吗?我应该手动调用一些记录较差的清理功能吗?这是错误吗?这会在每个系统上发生吗?
Internet上似乎存在一些类似的问题,但是令我惊讶的是,即使在最简单的用例中,这种情况也会发生。
编辑:因为已经进行了很多讨论,所以我将澄清一下:bruno的答案当然是正确的,这不是传统意义上的内存泄漏,并且在几乎所有平台上都没有关系(我包括Linux标记,这是一个错误,我现在已将其删除),但我仍然想知道这是否真的有意或是否发生,因为只有在valgrind生成其统计信息之后才释放内存,并且是否有任何方法可以解决这个问题(或至少让valgrind忽略它,以免在我其余的代码中掩盖丢失的free
调用)
答案 0 :(得分:10)
GNU readline:大量内存泄漏
==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 ...
可达内存不是内存泄漏
==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 使用了内存并仍然引用它,不要忘记它管理着历史记录,可以通过调用void rl_clear_history (void)
释放历史记录,在程序中添加该函数调用并重做测试
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.