C++递归全磁盘遍历fs::recursive_directory_iterator抛异常排查
磁盘遍历异常原因分析
直接触发异常的代码缺失项
- 异常捕获范围完全错位:你将
try块写在范围for的循环体内部,仅能捕获循环体中fs::is_directory、路径打印操作的异常。但fs::recursive_directory_iterator的**构造过程、迭代器自增(跳转到下一个条目)**均发生在范围for的初始化、迭代步骤中,完全不在try块的捕获范围内。遇到权限不足目录、未就绪可移动磁盘(如空光驱)、系统保护路径时,迭代器本身就会抛出异常,直接终止程序。 - 未配置迭代器错误跳过选项:默认构造的
fs::recursive_directory_iterator遇到任何无法访问的条目都会直接抛异常,没有传入fs::directory_options::skip_permission_denied参数跳过无权限的系统目录。
其他逻辑隐患
- 盘符获取逻辑硬编码遍历上限:你写死
i < 100遍历缓冲区,最多只能识别25个盘符,若系统盘符超过该数量会直接漏读;同时未处理GetLogicalDriveStringsA返回值大于缓冲区大小的场景,会因缓冲区不足截断盘符列表。 - 异常捕获块为空:即使捕获到异常也没有任何日志输出,无法定位具体是哪个路径访问失败。
修复参考实现
#include <iostream> #include <Windows.h> #include <vector> #include <string> #include <filesystem> namespace fs = std::filesystem; std::vector<std::string> getDrive() { std::vector<std::string> Drives; // 动态获取所需缓冲区大小,避免硬编码MAX_PATH导致盘符截断 DWORD bufSize = GetLogicalDriveStringsA(0, nullptr); if (bufSize == 0) return Drives; char* lDrives = new char[bufSize](); if (GetLogicalDriveStringsA(bufSize, lDrives)) { // 按双null终止的字符串格式遍历,不硬编码循环次数 char* p = lDrives; while (*p != 0) { Drives.push_back(std::string(p)); p += strlen(p) + 1; } } delete[] lDrives; return Drives; } int main() { std::vector<std::string> diskdrives = getDrive(); for (auto drv : diskdrives) { // 将迭代器构造、遍历全流程纳入异常捕获范围 try { // 传入跳过权限不足的选项,避免无权限目录直接抛异常 fs::recursive_directory_iterator iter(drv, fs::directory_options::skip_permission_denied); for (auto& file : iter) { try { if (!fs::is_directory(file)) { std::cout << file.path().string() << std::endl; } } catch (const std::exception&) { continue; } } } catch (const std::exception&) { // 捕获未就绪磁盘、损坏路径等构造阶段的异常 continue; } } return 0; }
内容的提问来源于stack exchange,提问作者Aorta 2k
相关产品推荐
相关产品推荐

