redirigir stdout / stderr al archivo bajo unix c ++ - otra vez

Lo que quiero hacer

redirigir stdout y stderr a uno o más archivos desde c ++

Por que lo necesito

Estoy utilizando una biblioteca externa de terceros precompilada que produce una cantidad ridícula de resultados, que me gustaría redirigir a un archivo de registro para mantener limpia la consola.

Condiciones

La compatibilidad no es un problema, el código solo se ejecutará en sistemas Unix. La redirección no solo debe afectar la impresión de estilo c ++ (std :: cout << "hello world" << std :: endl), sino también la impresión de estilo c (printf ("hello world \ n")).

Lo que he intentado hasta ahora

He estado navegando en stackoverflow durante medio día, leyendo varias respuestas a personas que tienen problemas similares. Con la ayuda de estas respuestas, he podido reunir el siguiente código:

#include <stdio.h>
#include <iostream>
#include <fcntl.h>
#include "unistd.h"

const int stdoutfd(dup(fileno(stdout)));

int redirect_stdout(const char* fname){
  fflush(stdout);
  int newstdout = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP |     S_IROTH);
  dup2(newstdout, fileno(stdout));
  close(newstdout);
}

int restore_stdout(){
  fflush(stdout);
  dup2(stdoutfd, fileno(stdout));
  close(stdoutfd);
  return stdoutfd;
}

int main(){
  redirect_stdout("/dev/null");
  std::cout << "invisible 1" << std::endl;
  restore_stdout();
  std::cout << "visible 1" << std::endl;
  redirect_stdout("/dev/null");
  std::cout << "invisible 2" << std::endl;
  restore_stdout();
  std::cout << "visible 2" << std::endl;
  return 0;
}

Lo que esperaría ver:

visible 1
visible 2

Lo que realmente veo

visible 1

Es decir, cuando se utiliza este mecanismo por primera vez, funciona, pero si se usa de nuevo, restaurar la salida no funcionará. ¿Alguien me puede indicar qué debo cambiar para que el mecanismo funcione infinitamente?

Respuestas a la pregunta(5)

Su respuesta a la pregunta