c - 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 运行sort
后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)
最后的调用。
我的问题是
- 这可能是 valgrind 的问题
sort
吗? - 我怎样才能进一步调试呢?
我仔细检查了程序中的每个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
解决方案
是的,valgrind
可以报告/usr/bin/sort
程序中的问题。
您的 shell 可能用于fork
为要执行的命令创建一个(或多个)进程,然后调用某个exec..
函数来执行指定的程序。当exec
函数成功时,进程不再运行你的shell的代码,而是运行其他程序的代码。
如果您指示valgrind
检查子进程,它将继续跟踪您的 shell 执行的程序,因此它也会报告这些程序中可能出现的错误。当然,这些错误与您的 shell 无关。
要确认这一点,您可以比较类似命令行的结果,例如ls | sort
与ls | cat
.
确认这一点的另一种方法是sort
独立valgrind
于您的简单外壳运行。你可以试试
ls | valgrind sort
valgrind
如果您要检查的程序的混合输出令人困惑,您可以使用valgrind
's option--log-file=<filename>
选项将其输出重定向到文件。
正如Jabberwocky的评论中提到的,为了避免检查任何不相关的程序,您可以创建自己的(假的)程序,这些程序没有内存泄漏和内存访问错误。要检查您的 shell 实现中的错误,您的替换不需要sort
实际对行进行排序。唯一重要的是它不会产生任何错误/警告,valgrind
并且它的行为可能类似于sort
它从 读取数据stdin
和将数据写入到的方式stdout
,可选延迟。
推荐阅读
- excel - 在布尔 vba 中重命名图表
- sql-server - 大表更新最佳实践
- spring-boot - Spring boot CrudRepository 将数据插入数据库
- google-apps-script - 为什么 Google Apps 脚本不更新电子表格中的工作表数量?
- javascript - 数据未完全显示在条形图上
- jquery - Chrome 扩展 - 运行 ajax 并根据结果执行操作
- python - Flask WTForms 自定义验证器始终显示“用户名或密码不正确”
- php - PHP Traits 类属性返回 Null
- sql - 从包含大量列的 pandas Dataframe 创建 SQL 表
- mongodb - MongoDB 一对多查询