c++怎么防止文件写入一半程序崩溃_双缓冲与重命名机制【避坑】

夏枫酱_2775

夏枫酱_2775

2026-04-07

899人浏览

原创

c++oding="utf-8" ?>

文件崩溃损坏本质是原子性缺失,可靠方案唯有“不覆盖原文件+写完再切换”:linux/macos用临时文件+rename(需同挂载点、fsync后执行),windows用movefileex+write_through。

c++怎么防止文件写入一半程序崩溃_双缓冲与重命名机制【避坑】

崩溃时文件写入不完整,本质是原子性缺失

程序崩溃导致文件损坏,不是因为磁盘写得慢,而是因为 fwrite、ofstream::write 等操作本身不保证“写完才落盘”,更不保证“写失败就回滚”。操作系统和 C++ 标准库都只承诺数据进入内核缓冲区,实际刷盘时机由系统调度,崩溃瞬间缓冲区内容直接丢失。单靠 fflush 或 fsync 也不能解决——它们只确保已写入的数据落盘,但无法防止“写到一半就断电”。

真正可靠的方案只有两个核心原则:不覆盖原文件 + 写完再切换。其他技巧(如内存映射、日志结构)在简单场景下反而增加复杂度和风险。

用临时文件 + rename 实现原子替换(Linux/macOS)

rename 在同一文件系统上是原子操作:要么成功把新文件“闪现”为最终路径,要么完全失败,原文件毫发无损。这是 POSIX 保证的,也是最轻量、最通用的方案。

实操要点:

  • 临时文件必须与目标文件在同一挂载点(stat 查 st_dev),否则 rename 会失败并退化为复制+删除,失去原子性
  • 临时文件名建议用 mkstemp 生成(如 /path/to/file.tmp.XXXXXX),避免竞态和覆盖
  • 写完后务必调用 fsync 刷临时文件内容和元数据,再 rename,否则可能只重命名了空文件或部分数据
  • C++ 中推荐用 std::filesystem::rename(C++17),它底层调用系统 rename,但需确认编译器标准库实现是否真正原子(GCC libstdc++ 和 Clang libc++ 均满足)

示例关键片段:

C++ Code Review Master
C++ Code Review Master

组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。

下载
int fd = mkstemp(tmp_path.data()); // tmp_path 是 std::string
if (fd == -1) { /* handle error */ }
FILE* f = fdopen(fd, "w");
fwrite(data, 1, size, f);
fflush(f);
fsync(fd); // 必须!否则 rename 后可能读到脏数据
fclose(f);
std::filesystem::rename(tmp_path, final_path); // 原子替换

Windows 下 rename 不可靠?用 MoveFileEx 替代

Windows 的 rename 在跨卷或权限受限时可能复制而非原子移动,且 NTFS 的原子性边界比 POSIX 更模糊。此时应改用 Win32 API:MoveFileEx 配合 MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH。

注意点:

  • MOVEFILE_WRITE_THROUGH 强制绕过系统缓存,等同于 fsync 效果,避免 rename 后数据仍在缓存中
  • 临时文件必须用 CREATE_TEMPORARY 标志创建,减少磁盘压力;同时设置 FILE_ATTRIBUTE_HIDDEN 避免被误读
  • C++ 调用需包含 <windows.h></windows.h>,不能依赖 std::filesystem::rename——MSVC 的实现对原子性无明确保证

双缓冲只是优化手段,不能替代原子替换

有人以为“先写内存 buffer,再一次性 dump 到文件”就能防崩溃,这是误解。双缓冲(如 std::vector<char></char> + writev)只减少系统调用次数、提升吞吐,但一旦写入过程崩溃,文件仍处于中间状态。它解决的是性能问题,不是可靠性问题。

真正需要双缓冲的场景极少,常见误区包括:

  • 误以为 std::ofstream 的默认缓冲能防崩溃——其实缓冲区在用户态,崩溃照样丢
  • 在临时文件里做双缓冲写入却不 fsync——rename 后可能看到截断文件
  • 用 std::stringstream 拼接 JSON/XML 再写入,却忽略序列化失败时没清理临时文件,导致磁盘泄漏

临时文件写入完成后,记得 unlink(Linux)或 DeleteFile(Windows)失败路径的残留文件——虽然 rename 成功后它已无关,但失败时若不清理,下次可能因文件名冲突而写入失败。

最易被忽略的一点:测试时别只关进程,要模拟断电——比如 echo c > /proc/sysrq-trigger(Linux)或直接拔电源。很多“看起来正常”的实现,在硬中断下依然丢数据。

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

相关文章

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

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

下载

相关标签:

c++

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

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2023.08.07

2035

5

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.23

2962

1

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

2023.10.13

1016

3

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

2025.09.10

3339

7

pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.01

4264

5

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

2024.08.01

5497

7

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

2024.11.28

2362

7

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

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

2023.07.26

3119

3

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

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

2023.07.27

2678

6

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Conan 2 Essentials 免费课程
Conan 2 Essentials 免费课程

共0课时 | 0人学习

CMake 与 Conan 集成实践
CMake 与 Conan 集成实践

共0课时 | 0人学习

Conan 2 高级依赖模型介绍
Conan 2 高级依赖模型介绍

共0课时 | 0人学习