为什么将 wcout/wcerr 重定向到 /dev/null 会导致程序崩溃?

Rob*_*der 0 c++ redirect wofstream

考虑我的日志记录类

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我将跟踪设置为 DetailLevel (2),一切都很好。我所有的日志记录都会保存到文件中。但是如果我选择 OffLevel 或 ErrorLevel 我的程序就会崩溃..我的调试器不会打开,所以我添加了 cout << "." 在每一行(我讨厌这样做,但它有效),它向我指出

wcout.rdbuf(fout.rdbuf()); // redirect 'cout' to a 'fout'
Run Code Online (Sandbox Code Playgroud)

作为我的罪魁祸首...我先重定向 wcout,然后重定向 wcerr,它起作用了(但尚未调用 wcerr)

这就是我的问题?我应该先处理 wcout 吗?我先尝试冲洗..那不起作用..所以我不知道。我究竟做错了什么?

另外作为奖励......为什么在我关闭 LogWriter 之前我的所有输出都不会进入文件?IE LogWriter::Dispose()

Eug*_*ene 5

你会崩溃,因为wofstream fout("/dev/null");它是在堆栈上创建的,一旦你离开该函数就会被销毁。

/dev/null就像对待文件一样对待。也就是OutputErrorsToFile("/dev/null")里面调用StopOutput()。事实上你甚至不需要/dev/null:只需使用wcout.rdbuf(nullptr),它也应该工作得更快。

要立即写入文件,请调用.flush()或使用std::flush操纵器。