在 Linux 下使用 readdir 报错,通常有下面几类原因。我按最常见 → 较少见的顺序说明,并给出排查方法。
readdir 必须配合 opendir 使用:
DIR *dir = opendir(path);
if (dir == NULL) {
perror("opendir");
return -1;
}
❌ 错误示例:
DIR *dir;
readdir(dir); // 未初始化,直接崩或报段错误
✅ 解决:
opendir 返回值readdir 原型是:
struct dirent *readdir(DIR *dirp);
❌ 错误:
FILE *fp = fopen(path, "r");
readdir(fp); // 错误类型
✅ 解决:
DIR *FILE *例如:
closedir(dir);
readdir(dir); // 未定义行为
✅ 解决:
closedir 后不要再调用 readdirreaddir 返回 NULL 的两种情况struct dirent *entry = readdir(dir);
if (entry == NULL) {
// 可能是:
// 1. 目录读取结束(正常)
// 2. 发生错误(需 errno 判断)
}
✅ 正确写法:
errno = 0;
entry = readdir(dir);
if (entry == NULL) {
if (errno != 0) {
perror("readdir");
} else {
// 正常结束
}
}
readdir 不是线程安全函数readdir ❌ 线程不安全readdir_r ✅(已废弃)readdir_r 替代方案:用 mutex 或 openat + getdents✅ 多线程中:
pthread_mutex_lock(&dir_lock);
readdir(dir);
pthread_mutex_unlock(&dir_lock);
| errno | 含义 |
|---|---|
| ENOENT | 目录不存在 |
| EACCES | 权限不足 |
| EBADF | DIR* 非法 |
| ENOTDIR | 不是目录 |
| EMFILE / ENFILE | 文件描述符耗尽 |
#include <dirent.h>
#include <stdio.h>
#include <errno.h>
int main() {
DIR *dir = opendir(".");
if (!dir) {
perror("opendir");
return 1;
}
struct dirent *ent;
errno = 0;
while ((ent = readdir(dir)) != NULL) {
printf("%s\n", ent->d_name);
}
if (errno != 0)
perror("readdir");
closedir(dir);
return 0;
}
你可以贴出:
errno)我可以直接帮你定位是哪一行的问题。