C++ <;系统错误>;类别和标准/系统错误代码

C++ <;系统错误>;类别和标准/系统错误代码,c++,c++11,winapi,posix,system-error,C++,C++11,Winapi,Posix,System Error,C++11引入了标题,其中包含处理错误代码的通用系统。std::error\u code是一个元组,包含int、错误代码和对std::error\u类别的引用,该类别定义了错误域和错误代码的处理。标准库有四个类别:std::generic_category,std::system_category,std::future_category,以及std::iostream_category P>在创建 STD::Error代码> /Calp>S/Pox STD::StulyOrgRebug <

C++11引入了
标题,其中包含处理错误代码的通用系统。
std::error\u code
是一个元组,包含
int
、错误代码和对
std::error\u类别的引用,该类别定义了错误域和错误代码的处理。标准库有四个类别:
std::generic_category
std::system_category
std::future_category
,以及
std::iostream_category

<> P>在创建<代码> STD::Error代码> /Calp>S/Pox<代码> STD::StulyOrgRebug < /Cult> s,代码< > ErnOn> /Cord>和WiAPI错误代码:< /P>时,在哪个C++类中使用哪些类冲突?
  • errno
    带有
    std::generic_category
  • errno
    带有
    std::system\u类别
  • GetLastError()
    带有
    std::generic\u category
  • GetLastError()
    带有
    std::system\u类别
但是,
errno
GetLastError()
不能使用相同的类别,否则某些错误代码将不明确。错误代码33是一个例子,因为它既是
EDOM
又是
Error\u LOCK\u违规

甚至有一些地方主张为WinAPI创建一个用户自定义的类别,但我目前找不到任何关于该类别的参考。这种选择将特别痛苦

哪个类别应与
errno
一起使用,哪个类别应与
GetLastError()
一起使用,以便

  • std::error\u code::default\u error\u condition()
  • std::error\u code::message()

对C++标准中的底层错误代码

是否是不恰当的?
system\u类别
缔约国指出:

C++标准库中的某些函数报告错误 通过
std::error\u code
(19.5.2.1)对象。那个 对象的
category()
成员应返回
std::system\u category()
对于源自操作系统的错误, 或引用定义的实现
错误\u类别
对象查找源自其他地方的错误。实施 应为每一项定义value()的可能值 错误>类别。 [示例:对于基于POSIX的操作系统, 鼓励实现定义
std::system\u category()
与POSIX
errno
值相同的值,并附加 由操作系统文档定义的值。 不基于POSIX的操作系统的实现 鼓励定义与操作参数相同的值 系统的值。对于非源于 在操作系统中,实现可能会为 关联值

不太清楚:

  • Windows上的
    errno
    值会发生什么情况

  • 来自POSIX调用的
    errno
    是“源于操作系统”还是仅限于非POSIX调用

通用类别
  • std::errc
    是一个枚举,其值与C/POSIX
    eFobar
    错误代码相同

    每个
    enum errc
    常量的值应与 上述概要中显示的
    宏的值。 实现是否公开
    宏未指定

  • 生成错误代码(std::errc)
    使用
    通用类别生成错误代码

    error\u code make\u error\u code(errc e)无异常;

    返回:
    error\u code(static\u cast(e),generic\u category())

这意味着POSIX错误代码可以与
generic_category
一起使用。非POSIX值可能无法与
generic_catgeory
一起正确工作。实际上,我使用的实现似乎支持它们

增强 增压系统本身 Boost文档非常简洁地介绍了此功能:

最初的提案将错误类别视为二元选择 在errno(即POSIX样式)和本机操作系统的 错误代码

此外,您还可以找到遗留声明,例如:

static const error\u category&errno\u ecat=generic\u category();

linux\u error.hpp
中:

要在API错误后构造错误代码:
error\u code(errno,system\u category())

windows\u error.hpp中

要在API错误后构造错误代码:
error\u code(::GetLastError(),system\u category())

cygwin\u error.hpp
中:

要在API错误后构造错误代码:错误代码(errno,system\u category())

对于Windows,Boost对非
errno
错误使用
system\u类别

ec = error_code( ERROR_ACCESS_DENIED, system_category() );
ec = error_code( ERROR_ALREADY_EXISTS, system_category() );
ec = error_code( ERROR_BAD_UNIT, system_category() );
ec = error_code( ERROR_WRITE_PROTECT, system_category() );
ec = error_code( WSAEWOULDBLOCK, system_category() );
在亚洲 我们在ASIO中发现此类代码:

template <typename ReturnType>
inline ReturnType error_wrapper(ReturnType return_value,
    boost::system::error_code& ec)
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
  ec = boost::system::error_code(WSAGetLastError(),
      boost::asio::error::get_system_category());
#else
  ec = boost::system::error_code(errno,
      boost::asio::error::get_system_category());
#endif
  return return_value;
}
文件系统 我们在POSIX代码中找到
errno
generic_category

int error = ::pthread_cond_init(&cond_, 0);
boost::system::error_code ec(error,
    boost::asio::error::get_system_category());
if (::chmod(p.c_str(), mode_cast(prms)))
{
  if (ec == 0)
    BOOST_FILESYSTEM_THROW(filesystem_error(
      "boost::filesystem::permissions", p,
      error_code(errno, system::generic_category())));
  else
    ec->assign(errno, system::generic_category());

}
在GNU libstdc中++ 文件系统 我们发现
errno
generic\u类别一起

if (char* rp = ::realpath(pa.c_str(), buf.get())) {
  [...]
}
if (errno != ENAMETOOLONG) {
  ec.assign(errno, std::generic_category());
  return result;
}
int ec = pthread_join(__t_, 0);
if (ec)
  throw system_error(error_code(ec, system_category()), "thread::join failed");
并且不使用
system\u类别

使用libstdc++ 实际上,您似乎可以使用libstdc++为非POSIX
errno
使用
generic\u category

std::error_code a(EADV, std::generic_category());
std::error_code b(EADV, std::system_category());
std::cerr << a.message() << '\n';
std::cerr << b.message() << '\n';
Libc++ 我们发现
errno
带有
system\u类别

if (char* rp = ::realpath(pa.c_str(), buf.get())) {
  [...]
}
if (errno != ENAMETOOLONG) {
  ec.assign(errno, std::generic_category());
  return result;
}
int ec = pthread_join(__t_, 0);
if (ec)
  throw system_error(error_code(ec, system_category()), "thread::join failed");
但不使用
通用类别

结论 我在这里找不到任何一致的模式,但显然:

  • 在Windows上使用Windows错误时,您需要使用
    system\u category

  • 对于
    errno

    generic_category