温馨提示×

Debian readdir内存

小樊
41
2026-07-27 23:38:15
栏目: 智能运维

Debian(以及 Linux 一般) 里,readdir 本身不会“一直涨内存”,但用错方式很容易造成内存泄漏或缓存增长。下面按常见情况给你一个清晰说明。


一、readdir 本身的内存行为(正常情况)

1️⃣ readdir()(传统接口)

#include <dirent.h>

DIR *dir = opendir(path);
struct dirent *entry;

while ((entry = readdir(dir)) != NULL) {
    // 使用 entry->d_name
}

closedir(dir);

正确使用时:

  • readdir() 返回的是 静态内部缓冲区
  • 不需要手动 free
  • 每次调用会覆盖上一次内容
  • 不会累积内存

错误用法:

char *name = strdup(entry->d_name); // 忘了 free

➡ 这是用户代码泄漏,不是 readdir 的问题。


2️⃣ readdir_r()(已废弃)

  • 需要你自己提供 buffer
  • 用错很容易内存出错
  • glibc 官方已不推荐

建议:用 readdir() 就够了


二、为什么你会看到“内存涨”?(Debian 常见原因)

✅ 1. 目录非常大(几万~几百万文件)

  • readdir 本身没问题
  • 内核 / glibc / 文件系统缓存会增长
free -h

你会看到:

  • buff/cache 变大
  • 这是 页缓存(page cache)
  • 不是内存泄漏
  • 会被自动回收

✅ 这是正常行为


✅ 2. 程序没关闭 DIR*

DIR *dir = opendir(".");
// 忘了 closedir(dir);

➡ 会造成:

  • fd 泄漏
  • 用户态内存增长
  • 长时间运行后 OOM

✅ 一定要:

closedir(dir);

✅ 3. 把 readdir 结果长期保存

struct dirent de;
struct dirent *entry;
readdir_r(dir, &de, &entry);
list_add(entry); // ❌

entry 是内部指针
✅ 正确做法:

strdup(entry->d_name);

三、Debian / Linux 特有注意点

1️⃣ ext4 / xfs / overlayfs

  • 对大目录:
    • readdir 会触发大量 dentry / inode 缓存
  • 表现:
    • slab 内存增长

查看:

slabtop
cat /proc/meminfo | grep -i slab

✅ 这是内核缓存,不是 bug


2️⃣ 容器 / Docker 里更明显

  • /proc/meminfo 看的是宿主机
  • 容器里 free 不准
  • readdir 后 cache 看起来像“内存泄漏”

✅ 正常现象


四、如何确认是不是真的泄漏?

1️⃣ 用 valgrind

valgrind --leak-check=full ./your_program

✅ 如果 readdir 本身泄漏,valgrind 会直接指出


2️⃣ 看是哪种内存涨

free -h
cat /proc/meminfo
类型 说明
buff/cache 正常
slab 内核缓存
anon 用户态泄漏

五、结论(重点)

readdir 本身不会内存泄漏
Debian 下内存涨通常是:

  • 文件系统缓存
  • 程序忘了 closedir
  • 错误保存 dirent 指针
  • 大目录 + 页缓存

如果你愿意,可以把:

  • 语言(C / C++ / Python / Go)
  • 目录规模(多少文件)
  • 内存增长截图 / free 输出

发出来,我可以精确判断是哪一种情况

0