redirecionar stdout / stderr para arquivo sob unix c ++ - novamente

O que eu quero fazer

redirecionar stdout e stderr para um ou mais arquivos de dentro de c ++

Porque eu preciso disso

Eu estou usando uma biblioteca externa, pré-compilada de terceiros que produz uma quantidade ridícula de saída, que eu gostaria de redirecionar para um arquivo de log para manter o console limpo.

Condições

A compatibilidade não é um problema, o código só será executado em sistemas Unix. O redirecionamento não deve afetar somente a impressão em estilo c ++ (std :: cout << "hello world" << std :: endl), mas também a impressão em estilo c (printf ("hello world \ n")).

O que eu tentei até agora

Eu tenho navegado em stackoverflow por meio dia, lendo várias respostas para pessoas com problemas semelhantes. Com a ajuda dessas respostas, consegui reunir o seguinte 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;
}

O que eu esperaria ver:

visible 1
visible 2

O que eu realmente vejo

visible 1

Ou seja, ao usar este mecanismo pela primeira vez, ele funciona - mas, se usado novamente, a restauração da saída não funcionará. Alguém pode me indicar o que preciso mudar para que o mecanismo funcione infinitamente?

questionAnswers(5)

yourAnswerToTheQuestion