I read a thoughtful series of blog posts about the new <system_error>
header in C++11. It says that the header defines an error_code
class that represents a specific error value returned by an operation (such as a system call). It says that the header defines a system_error
class, which is an exception class (inherits from runtime_exception
) and is used to wrap error_codes
s.
What I want to know is how to actually convert a system error from errno
into a system_error
so I can throw it. For example, the POSIX open
function reports errors by returning -1 and setting errno
, so if I want to throw an exception how should I complete the code below?
void x() { fd = open("foo", O_RDWR); if (fd == -1) { throw /* need some code here to make a std::system_error from errno */; } }
I randomly tried:
errno = ENOENT; throw std::system_error();
but the resulting exception returns no information when what()
is called.
I know I could do throw errno;
but I want to do it the right way, using the new <system_error>
header.
There is a constructor for system_error
that takes a single error_code
as its argument, so if I can just convert errno
to error_code
then the rest should be obvious.
This seems like a really basic thing, so I don't know why I can't find a good tutorial on it.
I am using gcc 4.4.5 on an ARM processor, if that matters.
Use asserts to check for errors that should never occur. Use exceptions to check for errors that might occur, for example, errors in input validation on parameters of public functions.
Exception handling in C++ consist of three keywords: try , throw and catch : The try statement allows you to define a block of code to be tested for errors while it is being executed. The throw keyword throws an exception when a problem is detected, which lets us create a custom error.
An exception should be thrown from a C++ constructor whenever an object cannot be properly constructed or initialized. Since there is no way to recover from failed object construction, an exception should be thrown in such cases.
Exception handling in C++ consists of three keywords: try, throw and catch: The try statement allows you to define a block of code to be tested for errors while it is being executed. The throw keyword throws an exception when a problem is detected, which lets us create a custom error.
You are on the right track, just pass the error code and a std::generic_category
object to the std::system_error
constructor and it should work.
Example:
#include <assert.h> #include <errno.h> #include <iostream> #include <system_error> int main() { try { throw std::system_error(EFAULT, std::generic_category()); } catch (std::system_error& error) { std::cout << "Error: " << error.code() << " - " << error.what() << '\n'; assert(error.code() == std::errc::bad_address); } }
Output from the above program on my system is
Error: generic:14 - Bad address
To add to the excellent accepted answer, you can enrich the error message with some contextual information in the 3rd argument, e.g. the failing file name:
std::string file_name = "bad_file_name.txt"; fd = open(file_name, O_RDWR); if (fd < 0) { throw std::system_error(errno, std::generic_category(), file_name); }
Then when caught, e.what()
will return, for example:
bad_file_name.txt: file not found
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With