C++使用std::filesystem遍历C盘如何避免Sharing Violation共享冲突错误
问题根因
fs::is_regular_file(fs::path)这类接收路径参数的类型判断函数,运行时会重新打开目标路径查询文件元数据。Windows系统下部分被进程独占锁定的文件(比如系统临时日志、驱动正在使用的文件)不允许额外的读取访问,就会触发32号共享冲突错误。
解决方案
方案1:使用directory_entry的缓存属性(最优)
recursive_directory_iterator返回的fs::directory_entry对象本身已经缓存了遍历阶段获取到的文件类型、大小等元数据,调用其自带的类型判断方法不需要再次访问文件,完全避免共享冲突:
- 判断普通文件用
p.is_regular_file() - 判断目录用
p.is_directory()
方案2:使用带error_code的重载(兜底方案)
如果确实需要主动查询路径的类型(比如缓存的元数据过期的特殊场景),调用带std::error_code参数的重载,避免抛出异常,错误发生时直接跳过即可:
std::error_code ec; bool is_regular = fs::is_regular_file(p.path(), ec); if (ec) { // 出现错误直接跳过当前文件/目录 continue; }
额外优化:遍历阶段直接跳过排除目录
你现有代码是遍历到子文件/子目录才判断是否属于排除路径,效率较低,可以在遍历到排除目录时直接关闭递归,无需进入遍历。
修改后的完整代码示例
#include <filesystem> #include <string> #include <iostream> #include <system_error> namespace fs = std::filesystem; int main() { fs::path rootPath = "C:\\"; fs::path exclPath = rootPath / "Windows"; fs::path drivrPath = rootPath / "drivers"; const fs::directory_options options = fs::directory_options::skip_permission_denied; for (auto& p : fs::recursive_directory_iterator(rootPath, options)) { // 先判断是否是排除目录,是则直接跳过递归 if (p.is_directory()) { if (p.path() == exclPath || p.path() == drivrPath) { p.disable_recursion_pending(); continue; } } std::string filePath = p.path().string(); // 直接用directory_entry的缓存方法判断类型,无共享冲突 if (!p.is_regular_file()) { std::cout << filePath << std::endl; } } return 0; }
内容的提问来源于stack exchange,提问作者Sad1que
相关产品推荐
相关产品推荐

