【问题标题】:What are the possible error codes that can be returned when calling std::filesystem::copy()?调用 std::filesystem::copy() 时可能返回的错误代码是什么?
【发布时间】:2020-03-13 15:03:49
【问题描述】:

我似乎找不到可能传递到std::filesystem::copyec 参数的错误代码列表。

cppreference.com 似乎表明错误代码是特定于操作系统的。
查看the Microsoft documentation(因为我对 Windows 错误代码特别感兴趣,但我确信其他操作系统的资源会有所帮助对于其他人)它看起来几乎是相同源文档的副本/粘贴,没有任何关于 Windows 特定的附加信息。

我的猜测是错误代码与here 列出的错误代码相同,但没有关于哪些与文件系统相关的信息,或者更具体地说是copy() 函数(超出有根据的猜测)。

是否有人有任何关于可能返回的潜在错误代码的资源,或者,如果我必须以艰难的方式执行此操作(并手动尝试检查不同的错误场景),我如何知道我是否有详尽的列表?

【问题讨论】:

  • MS 没有记录 WinAPI 函数的详尽列表 - 他们只是说调用 GetLastError。由于 C++ 运行时库实现最终必须调用 WinAPI 级别,我认为不可能获得完整的错误列表。作为示例,请参阅CreateFileW docs.microsoft.com/en-gb/windows/win32/api/fileapi/… "的文档...如果函数失败,则返回值为 INVALID_HANDLE_VALUE。要获取扩展的错误信息,请调用 GetLastError..."跨度>
  • 如果您有特定的用例,您希望根据错误代码执行不同的处理,您可以测试这些。然而,根据我的经验,这些很少见。例如,对于未找到文件,您将采取哪些不同的措施;拒绝访问;没有空间;网络故障等?
  • 您打算如何处理该错误? std::error_code 设计背后的全部意义在于,即使您对各个错误值一无所知,您仍然可以执行合理的错误处理。
  • 似乎没有任何关于如何处理错误值的信息(尤其是在我的用例中,我没有使用异常),除了知道出了什么问题。例如,我什至不确定如何检查函数是否因为目标路径中已经存在文件而失败。所以谢谢@ComicSansMS,你的答案正是我所需要的!我也一定会看看那篇博文

标签: c++ error-code std-filesystem


【解决方案1】:

文件系统库使用的系统特定错误代码可以是found in the __std_win_error enum。请注意数值如何 1:1 映射到 Win32 API 函数 GetLastError 返回的值:

enum class __std_win_error : unsigned long {
    _Success                   = 0, // #define ERROR_SUCCESS                    0L
    _Invalid_function          = 1, // #define ERROR_INVALID_FUNCTION           1L
    _File_not_found            = 2, // #define ERROR_FILE_NOT_FOUND             2L
    _Path_not_found            = 3, // #define ERROR_PATH_NOT_FOUND             3L
    _Access_denied             = 5, // #define ERROR_ACCESS_DENIED              5L
    _Not_enough_memory         = 8, // #define ERROR_NOT_ENOUGH_MEMORY          8L
    _No_more_files             = 18, // #define ERROR_NO_MORE_FILES              18L
    _Sharing_violation         = 32, // #define ERROR_SHARING_VIOLATION          32L
    _Not_supported             = 50, // #define ERROR_NOT_SUPPORTED              50L
    _File_exists               = 80, // #define ERROR_FILE_EXISTS                80L
    _Invalid_parameter         = 87, // #define ERROR_INVALID_PARAMETER          87L
    _Insufficient_buffer       = 122, // #define ERROR_INSUFFICIENT_BUFFER        122L
    _Invalid_name              = 123, // #define ERROR_INVALID_NAME               123L
    _Directory_not_empty       = 145, // #define ERROR_DIR_NOT_EMPTY              145L
    _Already_exists            = 183, // #define ERROR_ALREADY_EXISTS             183L
    _Filename_exceeds_range    = 206, // #define ERROR_FILENAME_EXCED_RANGE       206L
    _Directory_name_is_invalid = 267, // #define ERROR_DIRECTORY                  267L
    _Max                       = ~0UL // sentinel not used by Win32
};

但是,您不应该直接针对这些进行测试。 system_error 设计的全部意义在于不必直接解释特定于系统的error_codes,而只需通过它们关联的error_category 来解释它们。

特别是,类别将error_code 值映射到error_conditions。实现抛出error_code,但客户端应用程序应始终检查error_conditions。与error_code 不同,error_conditions 是可移植的,不依赖于实现细节。

因此,您应该如何处理代码中的这些类型的错误:检查std::errc 以获取您希望以编程方式处理的值。然后对照这些值检查error_code

std::error_code ec;
std::filesystem::copy("source.txt", "destination.txt", ec);
if (ec) {
    if (ec == std::errc::file_exists) {
        // special error handling for file_exists
        // [...]
    } else {
        // generic error handling for all other errors
        // that you don't specifically care about
        std::cerr << "Error: " << ec.message() << "\n";
    }
}

可能会遗留一些错误,但是由于您几乎可以肯定无论如何都无法为这些错误提供专门的错误处理程序,因此只需为您遇到的所有错误情况添加一个通用错误处理程序不在乎。

Chris Kohlhoff,系统错误库的原始作者之一,有一篇很棒的 blog seriesblog series 解释了错误处理机制的设计和预期用途。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 2013-01-14
    • 2011-01-29
    相关资源
    最近更新 更多