在 Debian(或任何 Linux)上使用 readdir / readdir_r 系列函数时,“内存泄漏”通常不是 readdir 本身造成的,而是使用方式不对。下面按常见场景说明如何避免。
readdir(推荐,最简单)readdir() 返回的是一个静态内部缓冲区指针,不需要(也不能)free。
#include <dirent.h>
#include <stdio.h>
int main() {
DIR *dir = opendir("/tmp");
if (!dir) return 1;
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir); // 必须关闭
return 0;
}
free(entry); // ❌ 错误,不该 free
✅ 结论:
free(readdir 的返回值)closedir()readdir_r(线程安全,但易出错)readdir_r 需要你自己提供 buffer:
DIR *dir = opendir("/tmp");
struct dirent *entry;
struct dirent *result;
entry = malloc(sizeof(struct dirent) + pathconf("/tmp", _PC_NAME_MAX) + 1);
readdir_r(dir, entry, &result);
free(entry); // ✅ 你自己 malloc 的
closedir(dir);
struct dirent entry; // ❌ 栈上可能不够大
readdir_r(dir, &entry, &result);
⚠️ 在某些系统上文件名很长会溢出。
opendir 必须 closedirDIR *dir = opendir(path);
if (!dir) { ... }
// 使用
closedir(dir);
如果中途 return / break / continue,也要保证关闭:
DIR *dir = opendir(path);
if (!dir) return;
if (error)
goto cleanup;
cleanup:
closedir(dir);
递归调用 opendir 时:
closedirscandir(小心返回数组)scandir 会 malloc 一个 struct dirent ** 数组:
struct dirent **namelist;
int n = scandir("/tmp", &namelist, NULL, alphasort);
for (int i = 0; i < n; i++) {
printf("%s\n", namelist[i]->d_name);
free(namelist[i]); // ✅
}
free(namelist); // ✅ 必须
❌ 忘记 free(namelist) 就是泄漏
sudo apt install valgrind
valgrind --leak-check=full ./your_program
gcc -fsanitize=address -g main.c
./a.out
✅ 记住这几点:
readdir() 不 freeclosedir() 必须调用readdir_r 的 buffer 自己管理scandir 返回数组要全 free如果你愿意,可以把你的 readdir 代码贴出来,我可以直接帮你指出哪里可能泄漏。