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_error
与 errno
和 WinAPI 错误代码:
-
errno
与std::generic_category
: SO answer , llvm-commits , cplusplus.com -
errno
与std::system_category
: SO answer , cppreference.com -
GetLastError()
与std::generic_category
: SO answer -
GetLastError()
与std::system_category
: SO answer , SO comment
但是,errno
和 GetLastError()
不能使用同一类别,否则有些错误代码会模棱两可。错误代码 33 是一个示例,因为它都是 EDOM
和 ERROR_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 上准确总结了它的工作原理,我不得不承认对
如果在 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())
其他想法:
一些评论员说
确实,如果 constexpr 全局变量在其设计时可用,今天看起来会大不相同,也许这可能会在 17 之后的 C++ 标准中得到纠正。但如果你是一个需要四处走动的程序员来自第三方库的错误代码不会丢失信息,通过代码不是为了了解这些第三方库而编写的,那么
将其视为类似于用于第三方库错误代码处理的 virtual
关键字 - 它消除了传输第三方代码的代码的需要,无需理解这些代码。如果您的代码库中存在这个问题 - 大多数大型代码库都有 - 那么您绝对应该使用
关于c++ - <system_error> 类别和标准/系统错误代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28746372/