首页 > 解决方案 > GNU readline:巨大的内存泄漏

问题描述

考虑以下代码段:

#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我其余代码中丢失的调用)

标签: cgnureadline

解决方案


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.

推荐阅读