温馨提示×

debian readdir怎么捕获异常

小樊
47
2026-09-25 15:27:56
栏目: 智能运维

在 Debian / Linux 下,使用 C/C++ 调用 readdir()(或 readdir_r())读取目录时,readdir() 本身并不通过返回值直接表示“异常”,而是通过 返回值和 errno 来捕获错误。

下面分情况说明。


一、常见误区

很多人以为 readdir() 会“抛异常”,其实:

  • readdir() 不会抛 C++ 异常
  • 出错时:
    • 返回 NULL
    • 同时设置 errno

二、基本用法(C 语言)

#include <dirent.h>
#include <errno.h>
#include <stdio.h>

int main() {
    DIR *dir = opendir("/some/path");
    if (dir == NULL) {
        perror("opendir");
        return 1;
    }

    struct dirent *entry;
    errno = 0;
    while ((entry = readdir(dir)) != NULL) {
        printf("%s\n", entry->d_name);
    }

    if (errno != 0) {
        perror("readdir");
    }

    closedir(dir);
    return 0;
}

关键点

  1. opendir() 失败 → 直接 perror
  2. readdir() 返回 NULL 时:
    • 可能是 正常结束
    • 也可能是 出错
  3. 判断方法:
    if (entry == NULL && errno != 0) {
        // 真正出错
    }
    

三、推荐做法(更清晰)

errno = 0;
entry = readdir(dir);
if (entry == NULL) {
    if (errno != 0) {
        perror("readdir failed");
    } else {
        // 正常遍历结束
    }
}

四、C++ 中“捕获异常”的方式

方式 1:自己抛异常(推荐封装)

#include <dirent.h>
#include <stdexcept>
#include <cerrno>
#include <cstring>

void read_directory(const char* path) {
    DIR* dir = opendir(path);
    if (!dir)
        throw std::runtime_error(std::string("opendir failed: ") + strerror(errno));

    struct dirent* entry;
    errno = 0;
    while ((entry = readdir(dir)) != nullptr) {
        // ...
    }

    if (errno != 0)
        throw std::runtime_error(std::string("readdir failed: ") + strerror(errno));

    closedir(dir);
}

使用:

try {
    read_directory("/tmp");
} catch (const std::exception& e) {
    std::cerr << e.what() << std::endl;
}

五、常见问题

1. readdir() 会返回 NULL 的两种情况

情况 errno
目录遍历结束 0
发生错误 ≠ 0

2. 线程安全

  • readdir() 不是线程安全
  • 多线程请用:
    • readdir_r()(旧)
    • 或 readdir() + 加锁
    • 或 C++17 std::filesystem

六、现代替代方案(推荐)

C++17

#include <filesystem>
namespace fs = std::filesystem;

for (auto& p : fs::recursive_directory_iterator("/some/path")) {
    // 自动抛异常
}

如果你能说明:

  • 用的是 C 还是 C++
  • 是否是 多线程
  • Debian 版本

我可以给你更精确的示例。

0 踩