不会自动抛异常;默认异常掩码关闭,拔盘后仅设failbit/badbit,需手动启用exceptions();is_open()始终返回true,不检测设备存在性;windows下原生api可捕获error_io_device,但std::ofstream会丢失错误码。

写文件时移动硬盘突然拔掉,std::ofstream 会抛异常吗?
不会自动抛 C++ 异常——默认情况下 std::ofstream 的异常掩码是关闭的,即使底层系统返回 EIO 或 ENODEV,流对象也只会静默设置 failbit,不会触发 std::ios_base::failure。这是最常被误以为“已捕获”的盲区。
- 必须手动开启异常掩码:
file.exceptions(std::ios::failbit | std::ios::badbit) -
badbit对应底层 I/O 错误(如设备断开、磁盘满),failbit更多是格式或逻辑失败(如 - 仅设
failbit不够——有些实现中拔盘只触发badbit,漏掉它就等于没捕获
write() 系统调用返回 -1 且 errno == EIO 怎么关联到 C++ 流?
C++ 标准库不保证把 errno 值透传给上层异常对象,也不能依赖 std::system_error 自动携带它。真正能拿到 EIO 的地方,是底层 write(2) 调用本身——这意味着你得绕过 std::ofstream,用 POSIX 接口直接控制。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 如果必须用
std::ofstream,异常对象里只有消息字符串(如"basic_ios::clear"),不含errno - 想区分
EIO和ENOSPC,得在写入前用fsync(2)+close(2)阶段检查errno,或改用open(2)/write(2)手动管理 fd -
std::ofstream的rdbuf()->pubsync()可触发一次刷新,但它不抛异常,只返回 -1;此时再查errno才有意义
拔盘后继续写文件,std::ofstream::is_open() 还返回 true 吗?
会。只要没显式调用 close() 或析构,is_open() 就始终返回 true——它只反映流对象是否绑定了有效 file descriptor,不检测设备是否存在。
- 拔盘后首次写入可能成功(数据还在 page cache),第二次才失败;
is_open()完全不可靠 - 不要用
is_open()做“设备在线”判断,它和硬件连通性零关系 - 真要探测,得用
ioctl(fd, BLKRRPART)或读取/sys/block/*/device/state(Linux),但跨平台成本高,不推荐实时轮询
Windows 上 WriteFile 返回 FALSE 且 GetLastError() == ERROR_IO_DEVICE 怎么对应?
这是 Windows 下最明确的拔盘信号,比 POSIX 的 EIO 更早、更稳定。但 C++ 标准流在 Windows 上默认走 CRT 封装,会把这类错误转成 badbit,丢失原始错误码。
- 若用原生 Win32 API:
WriteFile在拔盘后通常立即失败,GetLastError()返回ERROR_IO_DEVICE或ERROR_NO_MEDIA_IN_DRIVE - 用
std::ofstream时,开启异常掩码后捕获到std::ios_base::failure,再调用GetLastError()是无效的——CRT 已重置它 - 折中方案:写完关键数据后调用
FlushFileBuffers(hFile),失败时立刻查GetLastError(),比等析构时更及时
try/catch 覆盖所有情况,得按写入路径分段防御——尤其是 flush 和 close 这两步,最容易被忽略。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










