c++ - Windows 上不可靠的文件系统操作

标签 c++ windows winapi file-io filesystems

我不得不注意到 Bazaar 的一些奇怪行为我的机器上的目录锁定机制并尝试重现该机制。这是我的简单测试用例:

  1. 创建目录 Test,然后创建 Test/held,然后创建文件 Test/held/info

  2. Test重命名为YXCV

  3. 读取第 1 步中创建的文件(现在从路径 YXCV/held/info)。

  4. 清理(删除文件和目录)。

  5. 重复。

奇怪的是,这失败了。有时在步骤 2 中(“权限被拒绝”),有时在步骤 3 中(无法打开文件,尽管之后我可以在常规文本编辑器中打开该文件)。 有时会立即失败,有时会成功执行数千次迭代

我这里运行的是 Windows 7。我怀疑某些配置发生了变化(公司 IT 管理超出了我的控制范围),因为问题发生在一周前。

你知道任何可能的合理解释吗?

这是我的测试代码:

#include <iostream>
#include <fstream>

#include <direct.h>
#include <stdio.h>

void mkdir() {
    if ( mkdir( "Test" ) ) throw std::runtime_error( "mkdir" );
    if ( mkdir( "Test/held" ) ) throw std::runtime_error( "mkdir" );
}

void create() {
    if ( !std::ofstream( "Test/held/info" ).write( "asdf", 4 ) )
        throw std::runtime_error( "create" );
}

void rename() {
    if ( rename( "Test", "YXCV" ) ) throw std::runtime_error( "rename" );
}

void peek() {
    char buf[ 4 ];
    if ( !std::ifstream( "YXCV/held/info" ).read( buf, 4 ) )
        throw std::runtime_error( "peek" );
}

void del() {
    if ( unlink( "YXCV/held/info" ) ) throw std::runtime_error( "remove" );
    if ( rmdir( "YXCV/held" ) ) throw std::runtime_error( "remove" );
    if ( rmdir( "YXCV" ) ) throw std::runtime_error( "remove" );
}

void cleanup() {
    unlink( "Test/held/info" );
    rmdir( "Test/held" );
    rmdir( "Test" );
    unlink( "YXCV/held/info" );
    rmdir( "YXCV/held" );
    rmdir( "YXCV" );
}

int main() {
    cleanup();
    int count = 1;
    try {
        for ( ;; ++count ) {
            mkdir ();
            create();
            rename();
            peek  ();
            del   ();
        }
    }
    catch ( const std::exception &e ) {
        std::cout << "Run: " << count << "\nError: " << e.what() << "\n\t"
                  << strerror( errno ) << '\n';
    }
    std::cin.get();
}

最佳答案

当我单独运行你的程序时,它会永远循环而不会出现错误。

但是,一旦我使用其他程序同时执行一些文件系统操作,您的代码就会完全按照您所描述的那样失败:

  • 如果打开资源管理器窗口并在创建的叶目录中导航并留在那里,您的代码将无法删除或重命名目录(步骤 1 或 4)。
  • 如果我使用某些文本编辑器打开新文件,则文件读取失败(步骤 3)。

这是 Windows 文件系统上的正常行为。例如,如果程序在目录上有句柄,则无法删除该句柄(rmdir() 错误代码 EACCESS)。

您已经解释过您正在 Bazaar 版本管理目录结构中工作。这意味着一些后台服务进程会监视目录和文件的变化,并最终执行一些hooks and plugins (这可能会延长锁定条件)。这通常会产生上述锁定情况。

P.S:为了帮助您了解发生了什么,您可以使用 Microsoft 的 process explorer并使用 Ctrl+F 搜索文件句柄。在“句柄”字段中输入文件名,它将显示哪些进程使用该文件。注意:需要以管理员身份运行才能搜索系统进程。

关于c++ - Windows 上不可靠的文件系统操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33637513/

相关文章:

linux - 共享硬盘上的 Git 存储库

windows - 低完整性到中/高完整性管道安全描述符

c++ - 序列化结构的 STL 映射

c++ - 模板函数错误, "no matching function for call to..."

c - 异常的原因是什么?

c++ - 句柄无效(使用应用程序验证程序)

windows - 收集所有事件窗口类名

c++ - 为什么 stoi 函数在 Visual Studio 2010 中可用

c++ - 哪个类应该处理快捷方式?

c++ - opencv detectMultiScale