20

I know we can use

perror()

in C to print errors. I was just wondering if there is a C++ alternative to this, or whether I have to include this (and therefore stdio.h) in my program. I am trying to avoid as many C functions as possible.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
Sagar
  • 9,456
  • 6
  • 54
  • 96
  • 3
    For those who don't know, but immediately just say "use `cerr`", the usefulness of `perror()` is that it actually interprets the `errno` and displays it accordingly. I assume he wants the interpretation just as much as the console output... – KevenK Jul 23 '10 at 17:52
  • Could you please try to explain how you want to print errors? The C-functions are included in C++ as well, there's nothing wrong with using them. – Simon Jul 26 '10 at 20:05
  • 2
    Simon, one of the the reasons to avoid C-like printing functions in C++ programs is that some care (flushing) is needed when mixing e.g. `printf` and `cout`, see http://stackoverflow.com/questions/2708482 – Andre Holzner Feb 08 '11 at 11:15

3 Answers3

23

You could do something like:

std::cerr << strerror(errno) << std::endl;

That still ends up calling strerror, so you're really just substituting one C function for another. OTOH, it does let you write via streams, instead of mixing C and C++ output, which is generally a good thing. At least AFAIK, C++ doesn't add anything to the library to act as a substitute for strerror (other than generating an std::string, I'm not sure what it would change from strerror anyway).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • A C++ version of `strerror` which would return a `std::string` would presumably also be thread-safe, which would be a nice improvement. – Tyler McHenry Jul 23 '10 at 18:22
  • @Tyler: Well, that's certainly possible, and would be a handy improvement. OTOH, getting thread safety out of anything that uses `errno` almost unavoidably uses thread local storage anyway (i.e., about the same as it takes to make `strerror` thread safe). – Jerry Coffin Jul 23 '10 at 18:29
  • @Jerry I'm not sure about other threading frameworks, but POSIX threads guarantee that `errno` is thread-local automatically. The problem with `strerror` is that it returns a pointer to a static buffer that is not thread-local. – Tyler McHenry Jul 23 '10 at 21:28
  • @Tyler: My point was that to make `errno` work, you need to have and use TLS anyway, and once you're using it, you might as well use it for `strerror`'s buffer too. – Jerry Coffin Jul 23 '10 at 22:46
  • 1
    @Tyler McHenry: Having an error-message-creation-function that creates a std::string would be very inappropriate. How would that function work if it would try to report "out of memory"? I would say that an error-function that takes a char* buffer with a given size would be the most appropriate. It's also "thread-safe". – Simon Jul 26 '10 at 14:35
  • @Simon And there exists such a thing (`perror_r`), although you do have a point about out-of-memory errors. – Tyler McHenry Jul 26 '10 at 14:53
  • Thanks all. Really helpful! The fact that I can stream it makes me like it more. I don't like mixing C & C++ if I can help it. The sterror issue (non-local static buffers) is something I'll have to check, although we should be using POSIX threads, so... – Sagar Jul 26 '10 at 15:37
2

You could use the boost::system_error::error_code class.

#include <boost/system/system_error.hpp>

#include <cerrno>
#include <iostream>

void
PrintError(
        const std::string& message,
        int error
        )
{
    std::cerr << message << ": " <<
            boost::system::error_code(
                error,
                boost::system::get_system_category()
                ).message()
            << std::endl;
}

int
main()
{
    PrintError( "something went wrong!", EINVAL );
    return 0;
}

it's a tad verbose, and somewhat overkill if you aren't already using the boost_system library.

Sam Miller
  • 23,808
  • 4
  • 67
  • 87
  • Wouldn't that be pretty bad if you happen to do PrintError("We ran out of memory!", EINVAL); when you discover that you failed to do a memory-allocation? – Simon Jul 26 '10 at 14:36
  • 1
    Can't actually use the boost library. This has to be as 'plain' (for lack of a better term) as possible. Trying not to include any 3rd party stuff. Thanks though! – Sagar Jul 26 '10 at 15:35
1

With C++11, we have the <system_error> header, so you should be able to use:

std::error_code{errno, std::generic_category()}.message();

Example program:

#include <system_error>
#include <iostream>

int main() {
    std::cout << std::error_code{errno, std::generic_category()}.message() << '\n';
}

This prints Success.

See also:

einpoklum
  • 118,144
  • 57
  • 340
  • 684