【发布时间】: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