我想将std::cerr
和std::cout
的输出重定向到文件。为此,我使用了rdbuf
函数,如下面的代码示例所示。不幸的是,我收到了例外
Exception thrown: read access violation.
*(__imp_std::basic_ios<char,std::char_traits<char> >::rdbuf(...)) was 0xCCCCCCCC.
每当我尝试向std::cout
或std::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;
}
此示例创建两个文件,但不会将任何内容写入其中。我究竟做错了什么?
答案 0 :(得分:3)
std::ofstream
拥有自己的缓冲区,当std::ofstream
个对象超出范围时,它们会破坏缓冲区,导致std::cout
和std::cerr
使用无效的缓冲区指针。
确保不会过早删除缓冲区。
答案 1 :(得分:2)
用例如
std::cout.rdbuf(coutFile.rdbuf());
您使std::cout
分享与coutFile
相同的缓冲区,您只需设置指针。
不幸的是std::basic_streambuf
不是引用计数。这意味着当redirect
函数返回时,coutFile
被破坏并关闭,包括破坏缓冲区对象。
离开,例如std::cout
带有指向不存在的缓冲区对象的迷路指针。
您共享缓冲区对象的流需要在整个程序中具有生命周期。在退出程序之前,和需要恢复std::cout
和std::cerr
的原始缓冲区(rdbuf
返回指向旧缓冲区的指针)。