如何规避fs::directory_iterator异常及符号链接循环问题
问题
我正在用以下循环从根路径提取文件和目录名称:
for (const auto& entry : fs::directory_iterator(dirToList, fs::directory_options::skip_permission_denied, ec)) { // Doing some work }
我使用了ec来避免抛出exception,但仍出现以下错误:
terminate called after throwing an instance of 'std::experimental::filesystem::v1::__cxx11::filesystem_error' what(): filesystem error: status: Too many levels of symbolic links [/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/proc/self/task/92639/fd/4/media/floppy] Aborted (core dumped)
上述错误似乎由符号链接导致,因此我尝试用以下代码规避:
if(fs::is_symlink(entry, ec)){ std::cerr << "Avoiding symlink!" << std::endl; continue; }
但仍出现相同异常。
现提出两个问题:
- 如何解决上述问题?
- 如何彻底避免所有与
std::filesystem::experimental相关的异常?我希望采用返回错误的方式,不想处理异常。
解决方案
1. 解决符号链接循环异常
问题出在directory_iterator遍历过程中,隐式解析符号链接状态时陷入循环,此时你的符号链接判断代码还没执行就触发了异常。
修复步骤:
- 放弃范围for循环,改用显式迭代器递增并传入错误码,捕获遍历过程中的错误。
- 所有获取文件状态的操作必须传入
std::error_code,避免隐式抛出异常。 - 可提前跳过/proc、/sys这类特殊文件系统,从根源避免循环符号链接问题。
修复后的代码示例:
std::error_code ec; // 初始化迭代器时传入错误码 fs::directory_iterator iter(dirToList, fs::directory_options::skip_permission_denied, ec); if (ec) { std::cerr << "Failed to create directory iterator: " << ec.message() << std::endl; return; } for (; iter != fs::directory_iterator(); iter.increment(ec)) { // 检查迭代过程中的错误 if (ec) { std::cerr << "Iteration error: " << ec.message() << std::endl; ec.clear(); continue; } const auto& entry = *iter; // 显式获取文件状态,传入错误码 fs::file_status status = entry.status(ec); if (ec) { std::cerr << "Failed to get status for " << entry.path() << ": " << ec.message() << std::endl; ec.clear(); continue; } // 跳过符号链接 if (fs::is_symlink(status)) { std::cerr << "Skipping symlink: " << entry.path() << std::endl; continue; } // 执行你的业务逻辑 }
2. 彻底禁用std::filesystem::experimental异常
要完全避免异常,必须严格执行以下规则:
- 只使用带
std::error_code&参数的函数重载:所有std::filesystem函数都提供两个版本,带错误码的版本会将错误写入参数,不会抛出异常;不带的版本会在出错时抛出。 - 每次调用后立即检查错误码:调用函数后判断
ec是否被设置,处理错误后调用ec.clear(),避免错误状态影响后续操作。 - 避免隐式状态解析:不要使用
entry.is_symlink()这类无参数成员函数,必须先通过entry.status(ec)获取状态,再用fs::is_symlink(status)判断。 - 显式控制迭代器递增:不要用范围for循环遍历
directory_iterator,改用iter.increment(ec)显式递增,每次递增后检查错误。
只要全程遵循这些规则,就能确保所有std::filesystem::experimental操作都通过错误码返回结果,不会抛出任何异常。
内容的提问来源于stack exchange,提问作者noob_user
相关产品推荐
相关产品推荐

