首页 > 解决方案 > c 中的简单 shell - valgrind 显示排序命令的内存泄漏

问题描述

我正在用 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 运行后的输出,valgrind 运行sortls的泄漏总结为:

==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. 这可能是 valgrind 的问题sort吗?
  2. 我怎样才能进一步调试呢?

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

(如有必要,代码将更新)

更新

感谢Bodo的回答,我发现我的系统(VMware 16 下的 Linux 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

标签: cmemory-leaksvalgrind

解决方案


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

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

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

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


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

ls | valgrind sort

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


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


推荐阅读