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

Access violation exception while trying to redirect std::cerr to file

本文关键字:异常 访问冲突 文件 重定向 std cerr      更新时间:2023-10-16

我想将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;
}

此示例按原样创建两个文件,但不会将任何内容写入这两个文件。我做错了什么?

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

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

例如

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

你使std::coutcoutFile共享相同的缓冲区,你只设置指针

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

那留下例如std::cout带有指向不存在的缓冲区对象的杂散指针。

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