文件内容损坏的原因

时间:2011-06-29 19:13:14

标签: c++ windows winapi file-io corruption

我在应用程序中经常遇到问题。

它有一个相当简单的XML文件,它偶尔会丢弃,就像每30分钟一样。

数据文件通常很小 - 例如< 5KB。

它不会锁定文件 - 它只是每次都从头开始重新创建它。

我很幸运地看到问题发生在测试机器上,我观察到的是文件已损坏并设置为“nulls”(即十六进制中的00)。真正奇怪的是它与正确的长度完全相同。

我在保存过程中一直非常小心:

  1. 我将xml写入同一目录中的临时文件,因为我要真正保存它
  2. 我使用MOVEFILE_WRITE_THROUGH设置执行Win32 MoveFile()(因此阻止,直到移动真正完成),移动文件以替换现有数据文件
  3. 我甚至锁定互斥锁以确保这不是线程问题。

    通常不会发生,例如1000个用户中就有1个。

    现在,我在过去观察到数据文件在写入过程中被电源故障或BSOD损坏,我看到像32kb的文件都是NULL。

    但是,考虑到写入期间出现电源故障的可能性,以及特别是因为我正在使用MOVEFILE_WRITE_THROUGH,它似乎发生的事情比我预期的要多。

    有什么想法吗?

    约翰


    回答一些问题:

    • 问:为什么不直接写文件 答:我避免这种情况使软件不易受到电源故障的影响。例如。你正在编写文件和崩溃/ powerfail / BSOD的一半,那么你肯定有一个损坏的文件。执行临时文件写入然后执行移动是确保尽可能执行原子文件操作的常用且简单的方法(尽管在不使用NTFS特定API的情况下尽可能合理)。我应该说该软件是一个归档/备份系统,所以我必须比其他应用程序更加注意数据的一致性。

    • 问:这是否在正常操作期间发生?

    • 答:由于这个问题在野外发生,我只是在处理一些线索,所以我不确定。我可以说该软件在99.9%的时间内可靠运行。我想这就是我的问题的核心:这只是由BSOD /电源故障引起的随机不幸还是一个错误?

    • 问:什么环境/操作系统:

    • 答:XP,Vista,7,Server 200X。最有可能是NTFS,但可能是FAT32

    • 问:我在移动

    • 之前关闭了文件
    • 答:是的。我在使用C ++流并在执行MoveFile

    • 之前调用close()
    • 问:还有哪些进程正在访问该文件?

    • 答:没有我管理。显然,我无法控制病毒检查程序,文件夹同步器等。该文件位于用户计算机的AppData \ Local文件夹中。

2 个答案:

答案 0 :(得分:4)

根据我的经验,它可能是由Windows中的文件缓存引起的。您应该尝试使用CreateFile()FILE_FLAG_WRITE_THROUGH传入来保存文件。通过这种方式保存文件可以确保文件将落在硬盘中。

我试过一个小程序来测试它。如果程序使用std::ofstream创建文件并使用MoveFileEx()MOVEFILE_WRITE_THROUGH移动该文件,则文件移动完成后,如果关闭(不关闭)VM,文件几乎每次都会损坏;否则,如果程序使用CreateFile()FILE_FLAG_WRITE_THROUGH来创建文件并再次执行相同操作,则文件没有损坏(我测试了大约10次,但它没有发生)。

在这些简单的测试之后,我认为您应该尝试使用CreateFile()FILE_FLAG_WRITE_THROUGH来解决您的问题。

更多信息:
File Caching (Windows)
Windows Internals,第6版,第11章缓存管理器

答案 1 :(得分:0)

以下是一些想法:

  • 关键后冲洗流 信息或长期之前 没有写作。
  • 确认没有其他实体 写信给文件。
  • 验证缓冲数据不是 被其他代码覆盖。
  • 在较长时间内关闭文件 没有写作。