c 中的简单 shell - valgrind 显示排序命令的内存泄漏

simple shell in c - valgrind shows memorry leaks for sort command

我正在用 C 编写一个简单的 shell,它应该支持最多 2 个管道(我知道 n 个管道的实现更短,但出于某种原因这是特定要求)。

当使用 valgrind 检查内存泄漏时,我没有遇到任何问题,除非我使用 sort 命令,例如对于“ls | sort”输出以下消息:

==4903== HEAP SUMMARY:
==4903==     in use at exit: 760 bytes in 17 blocks
==4903==   total heap usage: 65 allocs, 48 frees, 8,533,744 bytes allocated
==4903== 
==4903== 8 bytes in 1 blocks are definitely lost in loss record 1 of 6
==4903==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4903==    by 0x11ACFC: ??? (in /usr/bin/sort)
==4903==    by 0x10D72A: ??? (in /usr/bin/sort)
==4903==    by 0x48AE0B2: (below main) (libc-start.c:308)
==4903== 
==4903== 32 bytes in 1 blocks are indirectly lost in loss record 2 of 6
==4903==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4903==    by 0x11ACFC: ??? (in /usr/bin/sort)
==4903==    by 0x1166F6: ??? (in /usr/bin/sort)
==4903==    by 0x10D860: ??? (in /usr/bin/sort)
==4903==    by 0x48AE0B2: (below main) (libc-start.c:308)
==4903== 
==4903== 48 bytes in 12 blocks are still reachable in loss record 3 of 6
==4903==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4903==    by 0x11ACFC: ??? (in /usr/bin/sort)
==4903==    by 0x10C122: ??? (in /usr/bin/sort)
==4903==    by 0x48AE0B2: (below main) (libc-start.c:308)
==4903== 
==4903== 128 bytes in 1 blocks are still reachable in loss record 4 of 6
==4903==    at 0x483B723: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4903==    by 0x483E017: realloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4903==    by 0x11AD69: ??? (in /usr/bin/sort)
==4903==    by 0x10F0F2: ??? (in /usr/bin/sort)
==4903==    by 0x10DA99: ??? (in /usr/bin/sort)
==4903==    by 0x48AE0B2: (below main) (libc-start.c:308)
==4903== 
==4903== 512 bytes in 1 blocks are indirectly lost in loss record 5 of 6
==4903==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4903==    by 0x11ACFC: ??? (in /usr/bin/sort)
==4903==    by 0x10D89D: ??? (in /usr/bin/sort)
==4903==    by 0x48AE0B2: (below main) (libc-start.c:308)
==4903== 
==4903== 576 (32 direct, 544 indirect) bytes in 1 blocks are definitely lost in loss record 6 of 6
==4903==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4903==    by 0x11ACFC: ??? (in /usr/bin/sort)
==4903==    by 0x1166C7: ??? (in /usr/bin/sort)
==4903==    by 0x10D860: ??? (in /usr/bin/sort)
==4903==    by 0x48AE0B2: (below main) (libc-start.c:308)
==4903== 
==4903== LEAK SUMMARY:
==4903==    definitely lost: 40 bytes in 2 blocks
==4903==    indirectly lost: 544 bytes in 2 blocks
==4903==      possibly lost: 0 bytes in 0 blocks
==4903==    still reachable: 176 bytes in 13 blocks
==4903==         suppressed: 0 bytes in 0 blocks
==4903== 
==4903== For lists of detected and suppressed errors, rerun with: -s
==4903== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

以上是 valgrind 运行 sort 后的输出,在 valgrind 运行 ls 后泄漏摘要是:

==4904== LEAK SUMMARY:
==4904==    definitely lost: 0 bytes in 0 blocks
==4904==    indirectly lost: 0 bytes in 0 blocks
==4904==      possibly lost: 0 bytes in 0 blocks
==4904==    still reachable: 20,381 bytes in 9 blocks
==4904==         suppressed: 0 bytes in 0 blocks
==4904== 
==4904== For lists of detected and suppressed errors, rerun with: -s
==4904== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

我可以忍受。

我尝试了几个不同的命令,有或没有管道 - 同样,sort 是唯一导致泄漏的命令。

当我退出程序时,valgrind 输出没有错误也没有内存泄漏,但这可能是由于最后的 exit(0) 调用。

我的问题是

  1. 这可能是 sort 的 valgrind 问题吗?
  2. 如何进一步调试它?

我仔细检查了我程序中的每个 free 调用,并在网上寻找类似的问题,但没有找到任何问题。

(代码会根据需要更新)

更新

感谢 Bodo 的回答,我发现我的系统(Linux VMware 16 下的 Mint 20)sort 确实导致内存泄漏,或者至少在 valgrind 中存在内存泄漏.我使用了 ls | valgrind sort 建议来解决这个问题。

valgrind 输出:

==2966== HEAP SUMMARY:
==2966==     in use at exit: 760 bytes in 17 blocks
==2966==   total heap usage: 65 allocs, 48 frees, 8,533,744 bytes allocated
==2966== 
==2966== LEAK SUMMARY:
==2966==    definitely lost: 40 bytes in 2 blocks
==2966==    indirectly lost: 544 bytes in 2 blocks
==2966==      possibly lost: 0 bytes in 0 blocks
==2966==    still reachable: 176 bytes in 13 blocks
==2966==         suppressed: 0 bytes in 0 blocks

是的,valgrind 可以报告 /usr/bin/sort 程序中的问题。

你的 shell 可能使用 fork 为要执行的命令创建一个(或多个)进程,然后调用一些 exec.. 函数来执行指定的程序.当 exec 函数成功时,进程不再是 运行 你的 shell 的代码,而是另一个程序的代码。

如果您指示valgrind检查子进程,它会继续跟踪您的shell执行的程序,因此它也会报告这些程序中可能存在的错误。当然这些错误与你的shell.

无关

要确认这一点,您可以比较类似命令行的结果,例如ls | sortls | cat.


确认这一点的另一种方法是 运行 sortvalgrind 独立于您的简单 shell。你可以试试

ls | valgrind sort

如果 valgrind 和您要检查的程序的混合输出令人困惑,您可以使用 valgrind 的选项 --log-file=<filename> 选项将其输出重定向到一个文件。


Jabberwocky 的评论所述,为避免检查任何不相关的程序,您可以创建自己的(假)程序,这些程序没有内存泄漏和内存访问错误。要检查 shell 实现中的错误,您对 sort 的替换没有必要实际对行进行排序。唯一重要的是它不会从 valgrind 产生任何 errors/warnings 并且它的行为可能与 sort 相似,从 stdin 读取数据并将数据写入到stdout,可选择延迟。