I am attempting to redirect cerr to a file at the start of a program, then at the end of the program set it back to normal. This is along the lines of the accepted answer of Use cout or cerr to output to console after it has been redirected to file
I am running into strange behavior in C++Builder for this. The environment seems to want me to refresh the stream redirection every time the program wants to output something.
I created the following test app to demonstrate the problem. If I comment out the #define on the first line, I get memory access violations. When the #define is uncommented, it seems to work fine while the program is executing; however, in a larger program, I believe I have also gotten the same memory access violations after the application terminates (works fine during execution with that #define in there – I still need to explore that one some more to track it down).
//#define MAKE_WORK
#include <vcl.h>
#pragma hdrstop
#include <fstream>
#include "TestRdbuf.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
std::streambuf* origBuff;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
std::ofstream oFile("ErrorLog.txt");
origBuff = std::cerr.rdbuf();
std::cerr.rdbuf(oFile.rdbuf());
std::cerr << "Started: " << Now() << std::endl;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
#ifdef MAKE_WORK
std::ofstream oFile("ErrorLog.txt", std::ios_base::app);
std::cerr.rdbuf(oFile.rdbuf());
#endif
std::cerr << "Closing:" << Now() << std::endl;
std::cerr.rdbuf(origBuff);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
#ifdef MAKE_WORK
std::ofstream oFile("ErrorLog.txt", std::ios_base::app);
std::cerr.rdbuf(oFile.rdbuf());
#endif
std::cerr << "Debug log time: " << Now() << std::endl;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnShowFileClick(TObject *Sender)
{
TMemo * Memo = new TMemo(pnlBody);
Memo->Parent = pnlBody;
Memo->Align = TAlign::alClient;
Memo->Font->Size = 12;
Memo->Lines->LoadFromFile("ErrorLog.txt");
Memo->ReadOnly = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
#ifdef MAKE_WORK
std::ofstream oFile("ErrorLog.txt", std::ios_base::app);
std::cerr.rdbuf(oFile.rdbuf());
#endif
std::cerr << "Exit clicked: " << Now() << std::endl;
Application->Terminate();
}
//---------------------------------------------------------------------------