c++ - <system_error> 类别和标准/系统错误代码

标签 c++ c++11 winapi posix std-system-error

C++11 引入了<system_error>包含处理错误代码的通用系统的 header 。一个 std::error_code是一个包含 int 的元组、错误代码和对 std::error_category 的引用,它定义了错误域和错误代码的处理。标准库自带四类:std::generic_category , std::system_category , std::future_category , 和 std::iostream_category .

在创建 std::error_code 时,在 SO 和 C++ 引用网站上都存在使用哪个类别的冲突。 s/ throw std::system_errorerrno和 WinAPI 错误代码:

但是,errnoGetLastError()不能使用同一类别,否则有些错误代码会模棱两可。错误代码 33 是​​一个示例,因为它都是 EDOMERROR_LOCK_VIOLATION .

甚至有些地方提倡为 WinAPI 建立用户自定义类别,但我目前找不到任何相关引用。这种选择会特别痛苦。

errno 应该使用哪个类别,并且应该与 GetLastError() 一起使用这样

  • std::error_code::default_error_condition()
  • std::error_code::message()

是否明确且适合底层错误代码?

最佳答案

鉴于 Chris 在 http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-1.html 上准确总结了它的工作原理,我不得不承认对 的混淆感到有点惊讶。我个人觉得上面的 C++ 标准文本非常清楚。但是用非常简洁的话来概括:

如果在 POSIX 上:

generic_category => POSIX 标准错误空间

system_category => 本地 POSIX errno 空间(通常使用专有的 errno 代码扩展 POSIX)。使用 strerror() 将代码展开为 message() 返回的字符串描述。

在 POSIX 上的实践中,两种实现在下面是相同的,并且映射了 native errno 空间。

如果在 Windows 上:

generic_category => POSIX 标准 errno 空间,由 MSVCRT 中的各种 POSIX 仿真函数返回,如 fopen()

system_category => Win32 GetLastError() 空间。使用 FormatMessage() 将代码展开为 message() 返回的字符串描述。

如何便携使用

std::error_code ec;
#ifdef _WIN32
if((HANDLE)-1 == CreateFile(...))
  ec = std::error_code(GetLastError(), std::system_category());
#else
if(-1 == open(...))
  ec = std::error_code(errno, std::system_category());
#endif
// To test using portable code
if(ec == std::errc::no_such_file_or_directory)
   ...
// To convert into nearest portable error condition (lossy, may fail)
std::error_condition ec2(ec.default_error_condition())

其他想法:

一些评论员说 设计不佳,不应该使用。这根本不是真的,考虑到其设计时间的 C++ 03 惯用实践,它在除 Dinkumware 之外的所有主要 STL 上生成非常紧凑的高质量固定延迟代码,这是非常理想的。用户可以将其扩展到任意错误代码系统,并将统一到单个系统中的不同第三方库错误处理标准化。

确实,如果 constexpr 全局变量在其设计时可用,今天看起来会大不相同,也许这可能会在 17 之后的 C++ 标准中得到纠正。但如果你是一个需要四处走动的程序员来自第三方库的错误代码不会丢失信息,通过代码不是为了了解这些第三方库而编写的,那么 是一个优秀的解决方案。

将其视为类似于用于第三方库错误代码处理的 virtual 关键字 - 它消除了传输第三方代码的代码的需要,无需理解这些代码。如果您的代码库中存在这个问题 - 大多数大型代码库都有 - 那么您绝对应该使用 而不是您当前使用的任何错误代码映射或翻译系统。

关于c++ - <system_error> 类别和标准/系统错误代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28746372/

相关文章:

c++ - 手动登录

c++ - FileCodeModel::AddFunction 在传递 vsCMFunctionConstructor 时生成具有返回类型的函数

c++ - 匿名聚合规则

c++ - 根据运行时数据选择函数重载?

c++ - 所有的模板实例都是在编译时创建的吗?

c++ - 如何遍历 getline() 中的每一行

c++ - 是否可以在另一个窗口中绘制(使用Opencv/ffmpeg

winapi - Win32 在父窗口中捕获子窗口消息

c++ - 发布版本中的程序崩溃

c++ - 为什么不能推导出这个metametafunction的模板参数呢?