c++怎么在写入文件流时检测捕捉磁盘物理扇区损坏导致的I/O报错【避坑】

千晨酱_9684

千晨酱_9684

2026-03-28

148人浏览

原创

write()返回0不表示成功,因c++流缓冲会掩盖底层i/o错误;必须flush()后检查failbit/badbit或用fsync()+errno捕获eio等物理层错误。

c++怎么在写入文件流时检测捕捉磁盘物理扇区损坏导致的i/o报错【避坑】

写入文件流时 write() 返回值为 0 不代表成功

很多 C++ 开发者默认 write() 或 ofstream::write() 写入后只要没抛异常就万事大吉,但磁盘扇区损坏(如坏道)常导致底层 write() 系统调用返回 0 或小于请求字节数,而 C++ 标准库流对象的 good()、fail() 在这种情况下可能仍返回 true——因为错误尚未被“刷新”到设备层。

关键点在于:C++ 流的缓冲机制会掩盖底层 I/O 错误,直到 flush() 或析构自动刷盘时才暴露问题。

  • ofstream::write() 后立即检查 !os.good() 很可能为 false,不能反映真实写入状态
  • 必须在 flush() 后立刻检查 failbit 或 badbit,否则可能误判成功
  • 若使用 std::ios_base::unitbuf 模式(或 std::cerr 默认行为),每次输出都强制刷盘,但性能代价大,且不解决根本检测逻辑

用 fsync() + errno 捕获底层磁盘 I/O 错误

标准 C++ 流不暴露底层文件描述符,也无法直接获取 errno。要真正捕获扇区级写入失败(比如内核返回 EIO),必须绕过流封装,用 POSIX 接口控制。

典型路径是:先用 open() 获取 fd → write() → fsync() → 检查 errno。其中 fsync() 是关键:它强制将数据和元数据刷到物理介质,坏扇区在此刻才会触发 EIO 或 ENOSPC 等错误。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • write() 成功只说明数据进了内核页缓存,不代表落盘
  • fsync() 失败(返回 -1)且 errno == EIO,基本可判定为物理介质故障(如扇区损坏、NVMe 坏块)
  • 注意:Windows 上需用 FlushFileBuffers() 替代 fsync(),且需通过 _get_osfhandle() 从 FILE* 或流中提取 HANDLE(不推荐混用 C++ 流和 WinAPI)

避免 ofstream 自动析构掩盖错误

ofstream 对象离开作用域时会自动 close(),而 close() 内部会尝试 flush() 和系统 close() 调用——但 C++ 标准规定:如果此时发生错误,close() 的失败**不会抛异常**(除非设置了 exceptions(ios_base::failbit | ios_base::badbit)),且错误状态可能被忽略。

这意味着:你没显式 flush() 和检查,又让流自动析构,坏扇区错误就彻底丢掉了。

  • 务必手动调用 os.flush(),然后立刻检查 os.fail() || os.bad()
  • 更稳妥做法:设置异常掩码,例如 os.exceptions(std::ofstream::failbit | std::ofstream::badbit),这样 flush() 失败会抛 std::ios_base::failure
  • 不要依赖析构做错误检测;析构期抛异常是危险行为(可能引发 std::terminate)

为什么 stat() 或 df 查不到扇区级损坏

文件系统工具(如 stat()、df -h)只报告逻辑空间使用和挂载状态,对已分配但物理不可写的扇区完全无感。坏扇区通常由硬盘固件在写入时首次发现并重映射(reallocation),此时上层看到的是 EIO,而非容量变化。

  • smartctl -a /dev/sdX 中的 Reallocated_Sector_Ct 或 Current_Pending_Sector 才是线索,但这属于事前预警,不是写入时的实时检测
  • 应用层唯一可靠方式,就是在每次关键写入后执行同步刷盘 + 错误检查
  • 高频检测成本高,建议只对关键日志、配置、事务性数据做 fsync() + errno 判断,普通数据流保持默认缓冲即可
事情说清了就结束。真正难的不是加几行检查代码,而是理解「写入完成」在 C++ 流、内核缓存、磁盘固件三层中的不同含义——漏掉任何一层,坏扇区就会静默吃掉你的数据。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

2023.10.19

3128

3

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

4749

12

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2025.12.29

3769

9

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

2026.01.19

446

15

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.26

3179

3

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.07.27

2758

6

windows照片无法显示
windows照片无法显示

当我们尝试打开一张图片时,可能会出现一个错误提示,提示说"Windows照片查看器无法显示此图片,因为计算机上的可用内存不足",本专题为大家提供windows照片无法显示相关的文章,帮助大家解决该问题。

2023.08.01

1488

3

windows查看端口被占用的情况
windows查看端口被占用的情况

windows查看端口被占用的情况的方法:1、使用Windows自带的资源监视器;2、使用命令提示符查看端口信息;3、使用任务管理器查看占用端口的进程。本专题为大家提供windows查看端口被占用的情况的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2519

5

windows无法访问共享电脑
windows无法访问共享电脑

在现代社会中,共享电脑是办公室和家庭的重要组成部分。然而,有时我们可能会遇到Windows无法访问共享电脑的问题。这个问题可能会导致数据无法共享,影响工作和生活的正常进行。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.08

3270

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习