剩余空间比例 = static_cast(space_info.available) / space_info.capacity,但available受权限、配额、预留空间等限制,并非用户可写上限;需校验capacity != 0且≠uint64_t(-1),避免除零或无效值。

std::filesystem::space() 返回的 available 和 capacity 到底怎么用
直接说结论:剩余空间比例 = static_cast<double>(space_info.available) / space_info.capacity</double>,但这个“可用”不是用户直观理解的“还能存多少”,它受权限、预留空间、配额等影响,available 可能远小于 free。
常见错误是拿 free 做分母,或者把 available 当作“用户可写入上限”直接用——结果在 root 分区或启用了配额的系统上严重高估可用率。
-
space_info.capacity是总字节数,通常可靠 -
space_info.free是未分配字节数(含保留空间),root 用户能用的部分 -
space_info.available是当前进程实际能写入的字节数,受 umask、quota、reserved blocks(如 ext4 的 5%)限制 - 计算比例时,必须检查
capacity != 0,否则除零崩溃;Linux 下某些虚拟文件系统(如/proc)可能返回uint64_t(-1)表示未知,需提前过滤
Windows 下 std::filesystem::space() 的兼容性坑
MSVC 19.28+ 和 GCC 10+ 在 Windows 上调用 GetDiskFreeSpaceEx(),但行为和 Linux 不一致:比如 NTFS 压缩卷中,available 按未压缩大小计算,而实际写入时压缩率不确定,导致比例失真。
更隐蔽的问题是权限:如果程序以普通用户运行,且目标路径在系统保护目录(如 C:Windows),space() 可能成功返回,但 available 为 0——不是磁盘满,而是访问被拒,此时不应报“空间不足”,而应检查错误码。
立即学习“C++免费学习笔记(深入)”;
- 调用后必须检查
space_info.capacity == uint64_t(-1),这是 Windows API 失败的标志(非异常,也不抛std::filesystem::filesystem_error) - 避免对网络路径(如
\servershare)直接调用,某些 SMB 版本不支持该查询,会静默返回全 -1 - 若需跨平台稳定行为,建议 fallback 到
GetDiskFreeSpaceExW()(Windows)或statvfs()(POSIX),绕过std::filesystem的封装差异
为什么 std::filesystem::space() 不抛异常却常返回无效值
标准规定:当无法获取信息时,space() 返回一个所有字段均为 uint64_t(-1) 的 space_info,而不是抛异常。这和 std::filesystem::file_size() 等函数不同,容易让人误以为“没出错就是有数”。
典型场景包括:路径不存在、权限不足、挂载点失效(如 NFS server down)、甚至某些容器环境中的 overlayfs 伪文件系统。
- 永远不要跳过有效性校验:
if (info.capacity == uint64_t(-1)) { /* handle error */ } - 不要依赖
exists(path)的结果来决定是否调用space()——路径存在不代表文件系统可查,反之亦然 - 在 CI 或容器中测试时,务必挂载真实块设备(如
/tmp绑定宿主机分区),否则默认的 tmpfs 可能返回恒定的 100% 可用,掩盖逻辑缺陷
计算剩余比例时的精度与整数溢出风险
直接用 double 转换看似安全,但 uint64_t 最大值约 1.8e19,而 double 只能精确表示 ≤2⁵³ 的整数(约 9e15)。当磁盘容量超 8PB,static_cast<double>(capacity)</double> 就会丢失低位精度,导致 0.1% 级别的误差。
这不是理论问题:云厂商的 EBS 卷、Ceph RBD 映像已普遍突破此量级。
- 若只需整数百分比,用整数运算更稳:
int percent = (info.available * 100) / info.capacity;
(注意先乘后除,避免截断) - 若需小数,改用
long double(GCC/Clang 支持 80-bit 扩展精度),或用__int128做中间计算(仅限支持平台) - 永远检查
info.capacity > info.available,某些损坏的文件系统或 FUSE 实现可能违反此基本约束
事情说清了就结束。真正难的不是算比例,而是理解 available 这个值背后有多少层抽象和妥协。



















