Question

I've been wondering, what is the point of clog? As near as I can tell, clog is the same as cerr but with buffering so it is more efficient. Usually stderr is the same as stdout, so clog is the same as cout. This seems pretty lame to me, so I figure I must be misunderstanding it. If I have log messages going out to the same place I have error messages going out to (perhaps something in /var/log/messages), then I probably am not writing too much out (so there isn't much lost by using non-buffered cerr). In my experience, I want my log messages up to date (not buffered) so I can help find a crash (so I don't want to be using the buffered clog). Apparently I should always be using cerr.

I'd like to be able to redirect clog inside my program. It would be useful to redirect cerr so that when I call a library routine I can control where cerr and clog go to. Can some compilers support this? I just checked DJGPP and stdout is defined as the address of a FILE struct, so it is illegal to do something like "stdout = freopen(...)".

  • Is it possible to redirect clog, cerr, cout, stdin, stdout, and/or stderr?
  • Is the only difference between clog and cerr the buffering?
  • How should I implement (or find) a more robust logging facility (links please)?
Was it helpful?

Solution

Is it possible to redirect clog, cerr, cout, stdin, stdout, and/or stderr?

Yes. You want the rdbuf function.

ofstream ofs("logfile");
cout.rdbuf(ofs.rdbuf());
cout << "Goes to file." << endl;

Is the only difference between clog and cerr the buffering?

As far as I know, yes.

OTHER TIPS

If you're in a posix shell environment (I'm really thinking of bash), you can redirect any file descriptor to any other file descriptor, so to redirect, you can just:

$ myprogram 2>&5 

to redirect stderr to the file represented by fd=5.

Edit: on second thought, I like @Konrad Rudolph's answer about redirection better. rdbuf() is a more coherent and portable way to do it.

As for logging, well...I start with the Boost library for all things C++ that isn't in the std library. Behold: Boost Logging v2

Edit: Boost Logging is not part of the Boost Libraries; it has been reviewed, but not accepted.

Edit: 2 years later, back in May 2010, Boost did accept a logging library, now called Boost.Log.

Of course, there are alternatives:

  • Log4Cpp (a log4j-style API for C++)
  • Log4Cxx (Apache-sponsored log4j-style API)
  • Pantheios (defunct? last time I tried I couldn't get it to build on a recent compiler)
  • Google's GLog (hat-tip @SuperElectric)

There's also the Windows Event logger.

And a couple of articles that may be of use:

Basic Logger

#define myerr(e) {CriticalSectionLocker crit; std::cerr << e << std::endl;}

Used as myerr("ERR: " << message); or myerr("WARN: " << message << code << etc);

Is very effective.

Then do:

./programname.exe 2> ./stderr.log
perl parsestderr.pl stderr.log

or just parse stderr.log by hand

I admit this is not for extremely performance critical code. But who writes that anyway.

Since there are several answers here about redirection, I will add this nice gem I stumbled across recently about redirection:

#include <fstream>
#include <iostream>

class redirecter
{
public:
    redirecter(std::ostream & dst, std::ostream & src)
        : src(src), sbuf(src.rdbuf(dst.rdbuf())) {}
    ~redirecter() { src.rdbuf(sbuf); }
private:
    std::ostream & src;
    std::streambuf * const sbuf;
};

void hello_world()
{
    std::cout << "Hello, world!\n";
}

int main()
{
    std::ofstream log("hello-world.log");
    redirecter redirect(log, std::cout);
    hello_world();
    return 0;
}

It's basically a redirection class that allows you to redirect any two streams, and restore it when you're finished.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top