std::filesystem::space 返回 0 通常因权限不足或路径无效;应传入挂载点根目录(如 "C:/" 或 "/"),而非子目录,且需捕获异常、校验路径存在性,优先使用 available 字段判断实际可用空间。

直接用 std::filesystem::space,别手写 WMI 或 ioctl——C++17 起标准库已原生支持,跨平台且线程安全。
为什么 std::filesystem::space 返回值有时是 0?
常见于权限不足或路径无效:Windows 下访问系统保留卷(如 \?Volume{...})、Linux 下挂载点被卸载但路径仍存在、或传入了非目录路径(比如指向文件的 path)。
- 确保传入的是**挂载点根目录**,不是普通子目录:
"C:/"可以,"C:/Users"不行(它不反映整个分区) - Linux/macOS 下必须是**实际挂载点**,
/home若是独立分区才有效;若只是/的子目录,返回的是根分区信息 - Windows 上路径末尾斜杠不能省:
"C:"会被视为相对路径,导致space抛std::filesystem::filesystem_error
std::filesystem::space 各字段的实际含义
space 返回 std::filesystem::space_info 结构体,三个字段单位全是字节,但语义不同:
-
capacity:分区总容量(含保留空间),和磁盘管理工具显示的“容量”一致 -
free:所有用户(含 root / Administrator)都可写的空闲字节数 -
available:当前进程**实际能写入**的字节数(已扣除 reserved blocks、quota 限制、配额余量等)——这才是你该关注的数字
例如在 ext4 上,若设置了 5% 保留空间给 root,则 free 比 available 大约多出 5%;普通用户程序应优先检查 available。
立即学习“C++免费学习笔记(深入)”;
Windows 下获取所有本地驱动器分区信息的最小可行代码
注意:需启用 C++17,链接 -lstdc++fs(GCC)或确保 MSVC 版本 ≥ 15.9:
#include <filesystem>
#include <iostream>
int main() {
// Windows: 枚举 C:, D: 等
for (char drive = 'C'; drive <= 'Z'; ++drive) {
std::filesystem::path p{std::string(1, drive) + ":/"};
if (!std::filesystem::exists(p)) continue;
try {
auto s = std::filesystem::space(p);
std::cout << p << ": "
<< "avail=" << s.available << " B
";
} catch (const std::filesystem::filesystem_error&) {
// 权限拒绝或未就绪(如光驱无盘)
continue;
}
}
}
Linux/macOS 替换为读取 /proc/mounts 或 getmntent 再逐个调用 space,不要硬编码路径。
性能与线程安全要注意什么?
std::filesystem::space 是系统调用封装(Windows 调 GetDiskFreeSpaceEx,Linux 调 statvfs),每次调用都有 I/O 开销:
- 避免在高频循环中反复调用——缓存结果,按需刷新(比如每 30 秒)
- 多个线程同时查同一路径是安全的,但查不同路径时,底层系统调用仍可能竞争(尤其 NFS/CIFS)
- 若需精确到毫秒级响应,且只关心是否低于阈值,可用
statvfs(Linux)或GetDiskFreeSpaceEx(Windows)绕过std::filesystem的异常封装,减少开销
真正容易被忽略的是:某些网络文件系统(如 SMB3、NFSv4.2)返回的 available 可能滞后数秒,不是实时值;业务逻辑里别把它当原子锁用。


















