C++ duplicate stdout to file by redirecting cout

2020-06-25 04:37发布

问题:

Good day.

I have to use some external functions that produce a lot of debugging information to stdout (via std::cout). I want to duplicate this information to some log file by redirecting cout to boost tee_device. I use the following example code:

typedef boost::iostreams::tee_device<ostream, ofstream> TeeDevice;
typedef boost::iostreams::stream<TeeDevice> TeeStream;

int main(int argc, char** argv) {

    remove("file.log");
    ofstream logFile;
    logFile.open("file.log");
    TeeDevice outputDevice(cout, logFile);
    TeeStream logger(outputDevice);    

    cout.rdbuf(logger.rdbuf());
    cout << "some log info";//this should print both to stdout and to file

    logger.close();
}

However I have a segmentation fault when trying to run this. Why?

I know that I can do like

    logger << "some debug log info";

but I need exactly to redirect cout. How I can obtain this?

Thanks, Stanislav

回答1:

You set TeeDevice output to std::cout, and then substitute it's rdbuf with one which depends on TeeDevice (which depends on std::cout).

Problem is solved by breaking that cycle via temporary std::ostream which holds pointer to original rdbuf of std::cout:

int main()
{
    remove("file.log");
    ofstream logFile;
    logFile.open("file.log");

    ostream tmp(cout.rdbuf()); // <----
    TeeDevice outputDevice(tmp, logFile); // <----
    TeeStream logger(outputDevice);    

    cout.rdbuf(logger.rdbuf());
    cout << "some log info" << endl;

    logger.close();
}

Live Demo on Coliru



回答2:

Try to use freopen function. Here is an example and comment from cplusplus.com:

This function is especially useful for redirecting predefined streams like stdin, stdout and stderr to specific files (see the example below).

/* freopen example: redirecting stdout */
#include <stdio.h>

int main ()
{
  freopen ("myfile.txt","w",stdout);
  printf ("This sentence is redirected to a file.");
  fclose (stdout);
  return 0;
}