0

consider my logging class

void LogWriter::InitLogWriter(void)
{
    wcout.flush();
    wcerr.flush();
    COUT_BACKUP = wcout.rdbuf(); // save original cout buffer
    CERR_BACKUP = wcerr.rdbuf(); //save original cerr buffer
    FileStreamOpen = false;
    switch(m_nTraceLvl)
    {
    case OffLevel:
        StopOutput();
        break;
    case ErrorLevel:
        OutputErrorsToFile(s_TraceFile);
        break;
    case DetailLevel:
        OutputAllToFile(s_TraceFile);
        break;
    default:
        StopOutput();
        break;
    }
    wcout << "Initialize Log Writer" << endl;
}
void LogWriter::OutputAllToFile(TCHAR* fileName)
{
    wstreambuf* fb = GetFileBufferStream(fileName);

    wcout.rdbuf(fb); // push wcout buffer to file
    wcerr.rdbuf(fb); // push cerr buffer to file

    FileStreamOpen = true;
}
void LogWriter::OutputErrorsToFile(TCHAR* fileName)
{
    wstreambuf* fb = GetFileBufferStream(fileName);
    wcerr.rdbuf(fb);
    FileStreamOpen = true;
    wofstream fout("/dev/null");
    wcout.rdbuf(fout.rdbuf()); // redirect 'cout' to a 'fout'
}
void LogWriter::StopOutput(void)
{
    wofstream fout("/dev/null");

    wcout.rdbuf(fout.rdbuf()); // redirect 'cout' to a 'fout'
    wcerr.rdbuf(fout.rdbuf()); // redirect cerr to fout
}
wstreambuf* LogWriter::GetFileBufferStream(TCHAR* fileName)
{
    filestr.open(fileName);
    return filestr.rdbuf();   // get file's streambuf
}
void LogWriter::Dispose()
{
    wcout << "Kill Log Writer" << endl;
    wcout.rdbuf(COUT_BACKUP); // restore the original stream buffer
    wcerr.rdbuf(CERR_BACKUP);

    if(FileStreamOpen)
    {
        filestr.close();
    }
}

Now if i set my Tracing to DetailLevel (2) all is fine. All my logging goes to the file. But if i choose OffLevel or ErrorLevel my program crashes.. my debugger doesn't turn on so i added cout << "." on every line (i hate doing that, but it works) and it points me to

wcout.rdbuf(fout.rdbuf()); // redirect 'cout' to a 'fout'

as being my culprit... I switched around redirecting wcout first with wcerr being redirected and it worked (but wcerr was not called yet)

so that is my question? am I supposed to dispose wcout first? I tried flushing first..that didn't work.. so i don't know. What am I doing wrong?

Also as a bonus.. how come all my output doesn't go to the file until I close my LogWriter? IE LogWriter::Dispose()

Daniel
  • 19,179
  • 7
  • 60
  • 74
Robert Snyder
  • 2,399
  • 4
  • 33
  • 65
  • i would simply use more well-defined functionality at bottom. C streams or even system specific code. it is important for loggers to be reliable. – Cheers and hth. - Alf Jan 15 '13 at 21:44
  • I think that might help...but I'm affraid I dont know what you mean. I'm a java/C# guy and got put into this C++ program. One problem i had was outputing large byte arrays (about 192bytes) and it would crash. When i switch to this, I don't have that problem – Robert Snyder Jan 15 '13 at 21:54
  • As for the bonus question -- std::fstream is buffered, so it will write when it feels like it, unless you flush it by "<< std::flush" or by calling flush on the stream (std::endl also calls flush). – Eugene Jan 15 '13 at 21:55
  • All of my log calls have endl (i use namespace std in stdafx.h) so it just doesn't make sense too me.. but i will try the std::flush thing.. I made a define of tout wcout << GetTime() << "\t" is there a way to ... just answered my question (how do i append << std::flush) use define...derp – Robert Snyder Jan 16 '13 at 02:51

1 Answers1

4

You crash because wofstream fout("/dev/null"); is created on the stack and is destroyed as soon as you quit the function.

Treat "/dev/null" exactly like you treat the file. That is, call OutputErrorsToFile("/dev/null") inside StopOutput(). In fact you don't even need /dev/null, just use wcout.rdbuf(NULL), should work faster too.

To write into the file immediately call flush or use std::flush manipilator.

Eugene
  • 7,180
  • 1
  • 29
  • 36