error_code: how to set and check errno

2020-03-23 06:23发布

问题:

I'm trying to understand what category I should use, when calling a C function that sets errno on Linux.

I'm not sure all the possible error codes are defined by POSIX, so I'm tempted to use the system_category.

But I like to handle generic condition in my code later on, so I would like to do things like that:

std::error_code ec;
some_func(some_path, ec);

if (ec) {
  if (ec == std::errc::file_exists) {
    // special handling
  }
  return ec;
}

To set the error code in some_func(), I expected to proceed like this:

ec.assign(EEXIST, std::system_category());

Mostly based on this discussion:

  • <system_error> categories and standard/system error codes
  • And the code sample provided by @niall-douglas:
std::error_code ec;
if(-1 == open(...))
  ec = std::error_code(errno, std::system_category());
// 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())

-- https://stackoverflow.com/a/40063005/951426

However, on Linux, with GCC 6.1.1, I have:

  • std::error_code(EEXIST, std::system_category()) == std::errc::file_exists returns false
  • std::error_code(EEXIST, std::generic_category()) == std::errc::file_exists returns true

I was expecting the errno + system_category to be comparable with std::errc conditions.

This means my initial code that checks if (ec == std::errc::file_exists) does not work if I don't use the generic category.

Is this the expected behavior?

回答1:

This is a bug recently fixed in latest GCC 6, 7 and 8 point releases. It'll work as you expect if you're on the latest point release. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60555.