尝试将std :: cerr重定向到文件时出现访问冲突异常

时间:2017-08-08 09:04:17

标签: c++ c++11 visual-c++ cout

我想将std::cerrstd::cout的输出重定向到文件。为此,我使用了rdbuf函数,如下面的代码示例所示。不幸的是,我收到了例外

Exception thrown: read access violation.

*(__imp_std::basic_ios<char,std::char_traits<char> >::rdbuf(...)) was 0xCCCCCCCC.

每当我尝试向std::coutstd::cerr写任何内容时。

以下是产生问题的代码示例:

void redirect()
{
    auto t = std::time(nullptr);
    auto tm = *std::localtime(&t);

    std::ostringstream oss;
    oss << std::put_time(&tm, "%Y-%m-%d_%H-%M-%S.log");
    auto cerrFileName = "cerr-" + oss.str();
    auto coutFileName = "cout-" + oss.str();


    std::ofstream cerrFile(cerrFileName, std::ios::ate); // file is created 
    std::cerr.rdbuf(cerrFile.rdbuf());

    std::ofstream coutFile(coutFileName, std::ios::ate); // file is created
    std::cout.rdbuf(coutFile.rdbuf());
}

int main()
{
    redirect();

    std::cout << "Test"; // The exception is thrown here.

    return 0;
}

此示例创建两个文件,但不会将任何内容写入其中。我究竟做错了什么?

2 个答案:

答案 0 :(得分:3)

std::ofstream拥有自己的缓冲区,当std::ofstream个对象超出范围时,它们会破坏缓冲区,导致std::coutstd::cerr使用无效的缓冲区指针。

确保不会过早删除缓冲区。

答案 1 :(得分:2)

用例如

std::cout.rdbuf(coutFile.rdbuf());

您使std::cout 分享coutFile相同的缓冲区,您只需设置指针

不幸的是std::basic_streambuf不是引用计数。这意味着当redirect函数返回时,coutFile被破坏并关闭,包括破坏缓冲区对象。

离开,例如std::cout带有指向不存在的缓冲区对象的迷路指针。

您共享缓冲区对象的流需要在整个程序中具有生命周期。在退出程序之前,需要恢复std::coutstd::cerr的原始缓冲区(rdbuf返回指向旧缓冲区的指针)。