C++ 如果cout、cerr和clog的rdbuf被更改为重定向到文件,是否需要重置它们?

C++ 如果cout、cerr和clog的rdbuf被更改为重定向到文件,是否需要重置它们?,c++,g++,C++,G++,在试图找出答案的时候,我注意到了一个链接。我用g++4.8.4尝试了上面链接答案中的代码,在程序终止之前出现了分段错误 节目如下: #include <iostream> #include <fstream> int main() { std::ofstream of("cout.txt"); std::cout.rdbuf(of.rdbuf()); std::cout << "test. test. test." << std

在试图找出答案的时候,我注意到了一个链接。我用g++4.8.4尝试了上面链接答案中的代码,在程序终止之前出现了分段错误

节目如下:

#include <iostream>
#include <fstream>

int main()
{
   std::ofstream of("cout.txt");
   std::cout.rdbuf(of.rdbuf());
   std::cout << "test. test. test." << std::endl;
   return 0;
}
来自
gdb
的输出:

GNU gdb(Ubuntu 7.7.1-0ubuntu5~14.04.2)7.7.1
版权所有(C)2014免费软件基金会。
许可证GPLv3+:GNU GPL版本3或更高版本
这是自由软件:您可以自由更改和重新发布它。
在法律允许的范围内,不存在任何担保。键入“显示复制”
和“显示保修”了解详细信息。
此GDB配置为“x86_64-linux-gnu”。
键入“显示配置”以获取配置详细信息。
有关错误报告说明,请参阅:
.
在线查找GDB手册和其他文档资源,网址为:
.
要获得帮助,请键入“帮助”。
键入“apropos word”以搜索与“word”相关的命令。。。
从socc读取符号…完成。
(gdb)运行
启动程序:/……../socc(此处删除了一些文本)
回溯(最近一次呼叫最后一次):
文件“/usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19-gdb.py”,第63行,在
从libstdcxx.v6.printers导入寄存器\u libstdcxx\u打印机
ImportError:没有名为“libstdcxx”的模块
程序接收信号SIGSEGV,分段故障。
0x000000000040073c英寸??()
(gdb)英国电信
#0 0x000000000040073c英寸??()
#1 0x0000000000000000英寸??()
(gdb)
我更新了程序,以保留
cout
的旧
rdbuf
,并在程序结束前重置它

#include <iostream>
#include <fstream>

int main()
{
   std::ofstream of("cout.txt");
   auto cout_buff = std::cout.rdbuf();
   std::cout.rdbuf(of.rdbuf());
   std::cout << "test. test. test." << std::endl;
   std::cout.rdbuf(cout_buff);
   return 0;
}
#包括
#包括
int main()
{
std::的流(“cout.txt”);
auto cout_buff=std::cout.rdbuf();
std::cout.rdbuf(of.rdbuf());
标准::cout引用Nicolai Josuttis第二版

第15.12.13章,重定向标准流,第822页

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

小心!对象
文件
是本地的,在块的末尾被销毁。这也会销毁相应的流缓冲区。这与“正常”不同流,因为文件流在构建时分配其流缓冲区对象,并在销毁时销毁它们。因此,在本例中,
cout
不能再用于写入。事实上,它甚至不能在程序终止时安全销毁。因此,旧缓冲区应始终保存并在以后还原


所以答案似乎是肯定的,尽管我没有一个标准的引用,但上面的作者是一位专家。

很好的发现。谢谢。你不一定需要把它换回来;问题是
基本文件buf
的生存期,如果你不把缓冲区改成其他东西,它必须比
cout
更久因此,您可以在最后执行
std::cout.rdbuf(nullptr);
而不是保存和恢复原始缓冲区。我从标准中注意到:~ios_base():析构函数不销毁rdbuf()。看起来像
~basic_fstream()
~basic_of stream()
销毁相应的
rdbuf()
@T.C.确实是的,否则析构函数可能会尝试双重删除。@vsoftco否,无论是
basic\u ios
还是
basic\u ostream
的析构函数都不会触及
rdbuf()
。这里的问题是
ios\u base::Init::~Init()
刷新流,如果流缓冲区没有了,这显然是不好的。