Reporting system errors in C++ is a daunting task. By system errors I mean
errors returned by standard C library functions, POSIX or Windows API.
In an ideal world you’d have a nice C++ API with errors reported as exceptions.
But often you need to use this nasty C function that indicates failure by a
special return value and sets errno
. Or even worse,
you have to call a Windows API function and the error code returned by
GetLastError
needs to be converted to a readable form via
FormatMessage
that will only appeal to you if you like functions
with 7 arguments with meaning of some of them depending on values of the other.
To cope with this, the C++ Format library now
provides two exception classes, SystemError
and
WindowsError
. The constructors of both classes take an error code,
a format string and arbitrary formatting arguments like the format
function. Each constructor formats the arguments according to the format string,
gets the error message corresponding to the error code and constructs an
exception object with the description of the form:
<your-message>: <system-error-message>
where <your-message>
is your formatted message and
<system-error-message>
is the system error message.
It is best illustrated with an example. Let’s say we need to open
a file and pass the FILE
object into some legacy C API.
That’s how you can do this with proper error handling using
SystemError
:
FILE *f = fopen(filename, "r");
if (!f)
throw fmt::SystemError(errno, "Cannot open file '{}'", filename);
If the file doens’t exist, this will throw SystemError
exception
with a description such as “Cannot open file ’test.log’: No such file or directory”.
And of course you can wrap this in a nice reusable RAII class that makes
sure the file is closed when the object is destroyed.
The second class, WindowsError
is similar, but it accept
error codes as given by GetLastError
on Windows. Obviously
this class is only available on Windows.
This functionality is available in C++ Format
version 0.10.0 and later. Unlike std::system_error
and friends,
it works with legacy compilers that don’t (fully) support C++11.
Update: brought the post up to date with the latest C++ Format API.
Last modified on 2014-04-30