C ++流的flush()和FindFirstFileEx()之间的竞争条件

时间:2012-06-22 11:41:47

标签: c++ winapi visual-c++ iostream

我的代码看起来很接近:

  1. 使用普通C ++ IO流插入(如steram << "foo";
  2. )进行大量写操作
  3. stream.flush();在某些时候;
  4. MSVC C API在上面的刷新后立即调用_stat()
  5. 我观察到的是,_stat()调用返回的尺寸与stream.tellp()不同,尺寸较小。

    如果在调用stream函数之前关闭_stat(),则会返回正确的结果。我已进入_stat()并使用FindFirstFileEx()来获取尺寸。

    这是一个已知的Win32 API怪癖吗?

3 个答案:

答案 0 :(得分:2)

我假设您正在使用Windows Vista或更高版本。每次将文件刷新到光盘时,文件大小都会在XP下的文件属性中更新。在Vista上已不再适用,因为Hans已经对文件属性进行了注释,并且在文件的最后一个句柄关闭时更新了它的大小。

有关详细信息,请参阅Old New Thing Blog

您可以尝试再次打开文件并关闭它。

答案 1 :(得分:1)

使用GetFileInformationByHandle获取确切的大小。

答案 2 :(得分:0)

这可能是由于文件系统缓存造成的。从C ++流的角度来看,它已按照标准的要求将所有写入的数据传递到物理设备。但是文件系统可能会缓存写入,并根据其他策略刷新它们。

可能的解决方案是使用以下Win32 API选项:

  1. 如果您碰巧使用CreateFile自行打开文件,请使用FILE_FLAG_NO_BUFFERINGFILE_FLAG_WRITE_THROUGH标记。
  2. 完成写作后,请调用FlushFileBuffers以确保刷新元数据(您必须以某种方式获取文件的句柄)。
  3. 假设您的C ++流正在进行自己的缓冲,这不会对性能造成太大影响。