--track-fds=yes 用于检测未关闭的文件描述符,跟踪 open、socket、pipe、eventfd、timerfd_create 等创建的 fd,不跟踪标准流及 dup 复制的 fd,退出时报告仍打开的 fd 及调用栈。

--track-fds=yes 主要用来暴露程序中被打开但未关闭的文件描述符(file descriptors),不是查内存,而是查系统资源泄漏。
哪些 fd 会被它跟踪
Valgrind 默认只跟踪由 open、socket、pipe、eventfd、timerfd_create 等系统调用直接创建的 fd。它不跟踪:stdin(0)、stdout(1)、stderr(2)这类标准流(除非你显式 dup 过它们),也不跟踪通过 dup/dup2/fcntl(F_DUPFD) 复制出来的 fd —— 除非原始 fd 本身也被跟踪(而默认情况下它不会递归追踪复制链)。
- 它能报告
open("/tmp/log.txt", O_WRONLY|O_CREAT)后忘记close()的情况 - 它能捕获
socket(AF_INET, SOCK_STREAM, 0)创建后未close()的 TCP/UDP socket - 它对
epoll_create1(0)、inotify_init1(0)这类内核对象 fd 也有效(只要底层是 fd)
典型错误输出长什么样
启用后,Valgrind 在程序退出时会汇总未关闭的 fd。例如:
==12345== FILE DESCRIPTORS: 3 open at exit. ==12345== Open file descriptor 3: /tmp/cache.dat ==12345== at 0x4C32B9F: open (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==12345== by 0x1087A1: init_cache (cache.c:42) ==12345== Open file descriptor 4: socket ==12345== at 0x4C32B9F: socket (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==12345== by 0x1088C5: start_server (server.c:67) ==12345== Open file descriptor 5: pipe ==12345== at 0x4C32B9F: pipe (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==12345== by 0x108922: spawn_worker (worker.c:33)
注意:它不会告诉你 fd 是不是“泄露”了(比如被覆盖丢失),只告诉你“还开着”。是否真构成问题,得结合业务逻辑判断 —— 比如一个长期运行的服务,每轮请求都漏一个 fd,迟早 hit EMFILE。
和 --leak-check 的关键区别
--track-fds=yes 和内存泄漏检测无关,也不依赖 --leak-check 参数。它独立工作,且开销极小(远低于 memcheck 本身)。但它有个硬限制:只在进程退出时报告,不支持运行中实时 dump。如果你需要监控某次函数调用前后 fd 数量变化,得自己封装 syscall(SYS_getdents64, ...) 或读 /proc/self/fd/ 对比。
另外,它对 /dev/xxx 类设备节点、/proc 下的伪文件、甚至 memfd_create 返回的 fd 都能识别并标记类型,但不会深入校验其使用是否合法(比如是否对只读 fd 调用了 write)。


















