std::fstream销毁时是否保证文件已写入磁盘?附代码示例
std::fstream文件写入时机与销毁时的磁盘写入保证
问题1:文件实际写入磁盘的时机是什么?当std::fstream被销毁时,是否能保证文件已写入磁盘?
文件实际写入物理磁盘的时机由多层缓存机制共同决定,主要场景包括:
- 用户态缓冲区触发刷新:当C++标准库的文件流缓冲区被填满、主动调用
std::flush/std::endl(endl会同时换行并刷新)、或调用流对象的flush()/sync()方法时,数据会从用户态缓冲区被送到操作系统的内核缓冲区。 - 内核缓冲区触发写入:操作系统会在自身内核缓存填满、系统空闲时,或者收到
fsync()(POSIX)/FlushFileBuffers()(Windows)这类系统调用时,才会把内核缓冲区的数据真正写入物理磁盘。 - 程序/流对象生命周期结束:程序正常退出时,操作系统通常会处理未写入的内核缓冲区数据;但异常退出时可能丢失数据。
关于std::fstream销毁时的保证:C标准只要求流对象销毁时自动关闭文件,关闭过程中会将用户态缓冲区的内容刷新到内核缓冲区,但不保证内核已将数据写入物理磁盘。内核到物理磁盘的写入是操作系统的调度行为,不受C标准控制。
问题2:给出的代码片段中,当std::fstream被销毁时,是否能保证文件已写入磁盘?
不能保证。
代码中使用std::endl确实会触发一次用户态缓冲区的刷新,将字符串送到内核缓冲区,但这只是完成了缓存传递的中间步骤。当std::fstream对象销毁时,同样仅确保用户态缓冲区数据进入内核缓存,无法保证物理磁盘已完成写入。
如果需要确保数据真正写入磁盘,必须在文件流关闭/销毁前调用系统级的同步函数,示例代码如下:
#include<iostream> #include<fstream> #include<cstdio> #ifdef _WIN32 #include<windows.h> #endif int main(int argc,char* argv[]) { { std::fstream file{"test.txt"}; file << "when the file is actually written out?" << std::endl; // 强制将内核缓存写入物理磁盘 #ifdef _WIN32 FlushFileBuffers((HANDLE)_fileno(file.rdbuf())); #else fsync(fileno(file.rdbuf())); #endif } return 0; }
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

