As far as I'm aware, my two options for handling stream errors are perror
and stream exceptions. Both options are undesirable. Here's why:
perror
std::strerror
returns an implementation-defined message. This message is not always useful on all systems
std::strerror
is not thread-safe
The pointer returned by std::strerror
can be invalidated
The C library is technically "deprecated" in C++. There's almost always a C++-ish equivalent. There's no reason why I should have to rely on POSIX and C when there's a potential C++ equivalent
stream exceptions
Exceptions are not appropriate for every program
While std::strerror
can sometimes provide a useful error message, stream exceptions never provide a useful error message. With f.exceptions(f.failbit)
, for both failure to open a file or failure to extract, the exception thrown is std::ios_base::failure
and the what()
is "basic_ios::clear
".
system_error
Replacing std::ios_base::failure
with std::system_error
produces exactly the same results. If we take a look at N2769: Detailed Reporting for Input/Output Library Errors (Revision 2)
, we can see why:
When throwing
ios_base::failure
exceptions, implementations are encouraged to provide values ofec
that identify the specific reason for the failure. [Note - Errors arising from the operating system would typically be reported assystem_category
errors with an error value of the error number reported by the operating system. Errors arising from within the stream library would typically be reported aserror_code(ioerrc::stream, iostream_category
) -- end note].The above wording provides only normative encouragement for implementers to do the right thing, and thus relies on market forces and the good intensions of implementers to produce results useful to users. Anything stronger (such as changing "are encouraged to" to "shall") would require much additional specification and is beyond the scope of what the LWG can realistically tackle for C++0x.
The alternative is to potentially rely on a bulky third party library (I'm looking at you Boost) or to hand-roll it (which you never want to do unless you know what you're doing.) I'm looking for the C++ standard library way to do this. Is there any?
The perror() function displays the description of the error that corresponds to the error code stored in the system variable errno . errno is a system variable that holds the error code referring to the error condition. A call to a library function produces this error condition.
The C library function void perror(const char *str) prints a descriptive error message to stderr. First the string str is printed, followed by a colon then a space.
Description. The perror() function prints an error message to stderr . If string is not NULL and does not point to a null character, the string pointed to by string is printed to the standard error stream, followed by a colon and a space.
Essentially the string representation of "errno" a global variable is printed out along with your arguments. If you have no errors (errono = 0). This is causing your program to print "SUCCESS".
I do not agree with you on
perror et alii are member of C standard library and as such technically deprecated(*).
Well even on cplusplus.com if not an official documentation source, I see for errno:
C++11 expands the basic set of values required to be defined in this header... In C++, errno is always declared as a macro, but in C it may also be implemented as an int object with external linkage.
My understanding of those sentences is that errno
is still considered in C++11!
I can even see later
Libraries that support multi-threading shall implement errno in a per-thread basis: With each thread having its own local errno. This is a requirement in libraries compliant with C11 and C++11 standards.
it means that even if strerror()
is not thread-safe, errno
is in any C++11 compliant implementation.
It is now up to you to use std::strerror
in a synchronized function (for example protected with a mutex) to build a std::string
if you like. But anyway, even if every documentation on strerror
states that it uses a static buffer that could be overwritten (that's why Posix 1 defines strerror_r), I could not find any warning on perror
not beeing thread safe.
(*) My opinion on that is that whenever OO and templates can give a nicer interface (iostream vs stdio.h or string vs. string.h), elements of the C library are replaced by others in C++ library. But when there is nothing to add (cerrno, cmath, csignal, etc.) the functions from C standard library are simply included in C++ one.
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