【问题标题】:memory leak occurs when run the code which includes popen运行包含 popen 的代码时发生内存泄漏
【发布时间】:2020-05-01 20:28:22
【问题描述】:

我正在使用 valgrind 调试简单的 popen 代码。

代码 popen_test.c

#include<stdio.h>
#include <unistd.h>

int main(void)
{
    FILE *fp;

    fp = popen("lsblk", "r");
    if (fp == NULL) {
        return -1;
    }

    pclose(fp);

    return 0;
}

编译命令

gcc -g -O0 popen_test.c

运行命令

valgrind --tool=memcheck --num-callers=30 --trace-children=yes --leak-check=full ./a.out

日志

==5993== Memcheck,内存错误检测器
==5993== 版权所有 (C) 2002-2017 和 GNU GPL,由 Julian Seward 等人提供。
==5993== 使用 Valgrind-3.14.0 和 LibVEX;使用 -h 重新运行以获取版权信息
==5993== 命令:./a.out
==5993==
==5994== Memcheck,内存错误检测器
==5994== 版权所有 (C) 2002-2017 和 GNU GPL,由 Julian Seward 等人提供。
==5994== 使用 Valgrind-3.14.0 和 LibVEX;使用 -h 重新运行以获取版权信息
==5994== 命令:/bin/sh -c lsblk
==5994==
==5995== Memcheck,内存错误检测器
==5995== 版权所有 (C) 2002-2017 和 GNU GPL,由 Julian Seward 等人提供。
==5995== 使用 Valgrind-3.14.0 和 LibVEX;使用 -h 重新运行以获取版权信息
==5995== 命令:/bin/lsblk
==5995==
==5995==
==5995== 进程以信号 13 (SIGPIPE) 的默认操作终止
==5995== 在 0x4A971E4:写入 (write.c:26)
==5995== by 0x4A43787: _IO_file_write@@GLIBC_2.17 (fileops.c:1188)
==5995== 由 0x4A42B87:new_do_write (fileops.c:456)
==5995== 由 0x4A4482F:_IO_new_do_write (fileops.c:433)
==5995== by 0x4A4482F: _IO_do_write@@GLIBC_2.17 (fileops.c:430)
==5995== 0x4A44147:_IO_file_close_it@@GLIBC_2.17 (fileops.c:136)
==5995== by 0x4A36CE7: fclose@@GLIBC_2.17 (iofclose.c:53)
==5995== 由 0x10EAEB: ??? (在 /bin/lsblk 中)
==5995== by 0x4A09CC7: __run_exit_handlers (exit.c:108)
==5995== 由 0x4A09E2B:退出 (exit.c:139)
==5995== by 0x49F5D27:(低于 main)(libc-start.c:342)
==5995==
==5995== 堆摘要:
==5995== 退出时使用:10 个块中的 16,735 个字节
==5995== 总堆使用量:1,136 次分配,1,126 次释放,2,262,873 字节分配
==5995==
==5995== 3 个块中的 12,639(12,456 个直接,183 个间接)字节在丢失记录 4 of 4 中肯定丢失了
==5995== 在 0x484A124:calloc (vg_replace_malloc.c:752)
==5995== 由 0x114ED3: ??? (在 /bin/lsblk 中)
==5995== 由 0x118153: ??? (在 /bin/lsblk 中)
==5995== 由 0x10ED6B: ??? (在 /bin/lsblk 中)
==5995== 由 0x10DC0F: ??? (在 /bin/lsblk 中)
==5995== by 0x49F5D23:(低于 main)(libc-start.c:308)
==5995==
==5995== 泄漏摘要:
==5995== 肯定丢失了:3 个块中的 12,456 个字节
==5995== 间接丢失:6 个块中的 183 个字节
==5995== 可能丢失:0 个块中的 0 个字节
==5995== 仍然可以访问:1 个块中的 4,096 个字节
==5995== 抑制:0 个块中的 0 个字节
==5995== 未显示可到达块(找到指针的块)。
==5995== 要查看它们,请重新运行:--leak-check=full --show-leak-kinds=all
==5995==
==5995== 对于检测到和抑制的错误计数,重新运行:-v
==5995== 错误摘要:来自 1 个上下文的 1 个错误(已抑制:来自 0 的 0 个)
==5994==
==5994== 堆摘要:
==5994== 退出时使用:30 个块中的 1,075 个字节
==5994== 总堆使用量:32 次分配,2 次释放,1,211 字节分配
==5994==
==5994== 泄漏摘要:
==5994== 肯定丢失:0 个块中的 0 个字节
==5994== 间接丢失:0 个块中的 0 个字节
==5994== 可能丢失:0 个块中的 0 个字节
==5994== 仍然可以访问:30 个块中的 1,075 个字节
==5994== 抑制:0 个块中的 0 个字节
==5994== 未显示可到达块(找到指针的块)。
==5994== 要查看它们,请使用以下命令重新运行:--leak-check=full --show-leak-kinds=all
==5994==
==5994== 对于检测到和抑制的错误计数,重新运行:-v
==5994== 错误摘要:0 个上下文中的 0 个错误(已抑制:0 个来自 0)
==5993==
==5993== 堆摘要:
==5993== 在退出时使用:0 个块中的 0 个字节
==5993== 总堆使用量:1 个分配,1 个释放,256 个字节分配
==5993==
==5993== 所有堆块都被释放——不可能有泄漏
==5993==
==5993== 对于检测到和抑制的错误计数,重新运行:-v
==5993== 错误摘要:0 个上下文中的 0 个错误(抑制:0 个来自 0)

我可以看到它为 popen 泄漏了内存。
我的代码有错误吗?或者如何使用 valgrind 是错误的?
你能帮我吗?

谢谢。

后记
我更改了代码以避免 SIGPIPE。

#include<stdio.h>
#include <unistd.h>

int main(void)
{
    FILE *fp;
    char var[256] = {0};

    fp = popen("lsblk", "r");
    if (fp == NULL) {
        return -1;
    }

    while (fgets(var, sizeof(var), fp) != NULL)
    {
        ;
    }

    pclose(fp);

    return 0;
}

==7778== Memcheck,内存错误检测器
==7778== 版权所有 (C) 2002-2017 和 GNU GPL,由 Julian Seward 等人提供。
==7778== 使用 Valgrind-3.14.0 和 LibVEX;使用 -h 重新运行以获取版权信息
==7778== 命令:./a.out
==7778==
==7779== Memcheck,内存错误检测器
==7779== 版权所有 (C) 2002-2017 和 GNU GPL,由 Julian Seward 等人提供。
==7779== 使用 Valgrind-3.14.0 和 LibVEX;使用 -h 重新运行以获取版权信息
==7779== 命令:/bin/sh -c lsblk
==7779==
==7780== Memcheck,内存错误检测器
==7780== 版权所有 (C) 2002-2017 和 GNU GPL,由 Julian Seward 等人提供。
==7780== 使用 Valgrind-3.14.0 和 LibVEX;使用 -h 重新运行以获取版权信息
==7780== 命令:/bin/lsblk
==7780==
==7780==
==7780== 堆摘要:
==7780== 在退出时使用:9 个块中的 12,639 个字节
==7780== 总堆使用量:1,136 次分配,1,127 次释放,2,262,873 字节分配
==7780==
==7780== 3 个块中的 12,639(12,456 个直接,183 个间接)字节在 3 个丢失记录 3 中肯定丢失了
==7780== 在 0x484A124:calloc (vg_replace_malloc.c:752)
==7780== 由 0x114ED3: ??? (在 /bin/lsblk 中)
==7780== 由 0x118153: ??? (在 /bin/lsblk 中)
==7780== 由 0x10ED6B: ??? (在 /bin/lsblk 中)
==7780== 由 0x10DC0F: ??? (在 /bin/lsblk 中)
==7780== by 0x49F5D23:(低于 main)(libc-start.c:308)
==7780==
==7780== 泄漏摘要:
==7780== 肯定丢失:3 个块中的 12,456 个字节
==7780== 间接丢失:6 个块中的 183 个字节
==7780== 可能丢失:0 个块中的 0 个字节
==7780== 仍然可以访问:0 个块中的 0 个字节
==7780== 抑制:0 个块中的 0 个字节
==7780==
==7780== 对于检测到和抑制的错误计数,重新运行:-v
==7780== 错误摘要:来自 1 个上下文的 1 个错误(已抑制:来自 0 的 0 个)
==7779==
==7779== 堆摘要:
==7779== 退出时使用:30 个块中的 1,075 个字节
==7779== 总堆使用量:32 次分配,2 次释放,1,211 字节分配
==7779==
==7779== 泄漏摘要:
==7779== 肯定丢失:0 个块中的 0 个字节
==7779== 间接丢失:0 个块中的 0 个字节
==7779== 可能丢失:0 个块中的 0 个字节
==7779== 仍然可以访问:30 个块中的 1,075 个字节
==7779== 抑制:0 个块中的 0 个字节
==7779== 未显示可到达块(找到指针的块)。
==7779== 要查看它们,请使用以下命令重新运行:--leak-check=full --show-leak-kinds=all
==7779==
==7779== 对于检测到和抑制的错误计数,重新运行:-v
==7779== 错误摘要:0 个上下文中的 0 个错误(已抑制:0 个来自 0)
==7778==
==7778== 堆摘要:
==7778== 在退出时使用:0 个块中的 0 个字节
==7778== 总堆使用量:2 个分配,2 个释放,分配 4,352 个字节
==7778==
==7778== 所有堆块都被释放——不可能有泄漏
==7778==
==7778== 对于检测到和抑制的错误计数,重新运行:-v
==7778== 错误摘要:来自 0 个上下文的 0 个错误(抑制:来自 0 的 0 个)

SIGPIPE 未显示,但看起来内存泄漏发生在 popen 进程上。

【问题讨论】:

    标签: c memory-leaks valgrind popen


    【解决方案1】:

    不,您的程序(在进程 5993 中)没有泄漏。

    ==5993== HEAP SUMMARY:
    ==5993== in use at exit: 0 bytes in 0 blocks
    ==5993== total heap usage: 1 allocs, 1 frees, 256 bytes allocated
    ==5993==
    ==5993== All heap blocks were freed -- no leaks are possible
    

    lsblk(在进程 5995 中)仍然分配了内存,但这是正常的,因为在程序完成之前进程已被(由 SIGPIPE)杀死。

    ==5995== Process terminating with default action of signal 13 (SIGPIPE)
    

    进程在写入已关闭的管道或套接字时会收到 SIGPIPE 信号。 (在这种情况下,lsblk 的标准输出。)

    【讨论】:

    • 感谢您的回复。我更改了代码以避免 SIGPIPE,但它看起来发生了内存泄漏。你会检查附言吗?谢谢。
    • 您的程序仍然没有泄漏。另一个程序有,但没有理由相信它与popen 有任何关系。
    猜你喜欢
    • 2014-07-10
    • 1970-01-01
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 2015-05-03
    相关资源
    最近更新 更多