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();
}
//---------------------------------------------------------------------------