已删除的文件仍被报告为存在(仅适用于Windows)

4

(请注意,这不是主要的Qt问题)

我觉得QFile::exists()的返回值有时是错误的。

考虑以下两个类似于单元测试的代码片段(我已经在循环中执行了数千次每个代码片段)

// create file
QFile file("test.tmp");
QVERIFY(file.open(QIODevice::WriteOnly));
QVERIFY(file.write("some data") != -1);
file.close();

// delete file
QVERIFY(file.remove());

// assert file is gone
QVERIFY(!file.exists());  // <-- 5..10 % chance of failure

并且

// create file
QFile file("test.tmp");
QVERIFY(file.open(QIODevice::WriteOnly));
QVERIFY(file.write("some data") != -1);
file.close();

// delete file
QVERIFY(file.remove());

// retry until file is gone (or until timeout)
for (auto i = 0; i < 10; i++)
{
  if (!file.exists())  // <-- note that only the check is retried, not the actual delete
    return;

  QThread::yieldCurrentThread();
}

QFAIL("file is still reported as existing");  // <-- never reached in my tests

第一个单元测试有大约100次中8次失败。总是在代码的最后一行(表示文件仍然存在)。第二个单元测试从不失败。
这种行为在使用NTFS的Windows 10系统上观察到(使用Qt 5.2.1),但无法在使用ext4的VM上的ubuntu 16.04 LTS上复现(使用Qt 5.8.0)。
不确定是否有帮助:
- 进程监视器(成功时) - 进程监视器(失败时) 因此,我的问题是:
- 发生了什么? - 我可能感兴趣的影响是什么?

更新:

澄清一下:我希望得到的答案类似于“这是由NTFS功能'账单花式缓存魔法'引起的”。然后我想知道,Qt是否有意查看此功能。


1
我建议这是一个非常关于Qt的问题,因为两个代码示例都使用了Qt类型或函数来执行每个语句。这些类型或函数的工作方式至关重要 - 例如,它们是否以某种方式锁定文件,可能会在关闭后防止其被删除?毫无疑问,如果没有了解Qt的工作原理,那么任何具有C++或Windows知识的人都无法帮助您。 - Peter
3
我会说 file.remove() 可能是一个非阻塞操作且是异步完成的。 - Jarod42
@Jarod42 这就是我所想的。然而,file.remove() 的 API 文档表明它“如果成功则返回 true;否则返回 false。”这对我来说并不像是一个异步实现。除此之外:在 Ubuntu / ext4 上按预期工作。 - simon
尝试使用QFileInfo和setCaching(false)。 - Deep
1
Windows 10 NTFS Qt 5.10.1 没有观察到使用 1MB 大小的测试文件... 另外,使用 QFileSystemWatcher 监视 fileChanged 然后检查 exists 怎么样? - JustWe
显示剩余5条评论
1个回答

0
根据Windows API文档,这是定义行为:
删除文件函数会在关闭时标记文件以进行删除。因此,直到关闭文件的最后一个句柄之前,文件删除才不会发生。随后对CreateFile的调用打开该文件将失败并显示ERROR_ACCESS_DENIED。
它似乎是Windows内核的属性,因此不仅限于NTFS。
该行为似乎是不可预测的,因为其他服务(如病毒扫描器)可能会打开相关的文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接