cout、cerr、clog的rdbuf改成重定向到文件后,是否需要重新设置?
Is it necessary to reset rdbuf of cout, cerr, and clog if they have been changed to be redirected to a file?
在思考如何回答时, I noticed a link to an answer to a related SO post。我用 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;
}
构建程序的命令:
g++ -Wall -std=c++11 -g socc.cc -o socc
来自gdb
的输出:
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from socc...done.
(gdb) run
Starting program: /.........../socc (removed some text here)
Traceback (most recent call last):
File "/usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19-gdb.py", line 63, in <module>
from libstdcxx.v6.printers import register_libstdcxx_printers
ImportError: No module named 'libstdcxx'
Program received signal SIGSEGV, Segmentation fault.
0x000000000040073c in ?? ()
(gdb) bt
#0 0x000000000040073c in ?? ()
#1 0x0000000000000000 in ?? ()
(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;
}
有了这个改动,程序运行就没有任何问题了。
我对 cerr
和 clog
进行了类似的实验,结果相同。
这让我想到以下问题:
如果 cout
、cerr
和 clog
已更改为重定向到文件,是否总是需要重置它们的 rdbuf
?
如果不是,这是 g++ 缺陷吗?
引自 The C++ Standard Library - A tutorial and reference Nicolai Josuttis 第 2 版,
通道。 2013 年 12 月 15 日,重定向标准流 第 822 页
...
std::cout.rdbuf (file.rdbuf());
Caution! The object file
is local and is destroyed at the end of the block. This also destroys the corresponding stream buffer. This differs from the “normal” streams because file streams allocate their stream buffer objects at construction time and destroy them on destruction. Thus, in this example, cout
can no longer be used for writing. In fact, it cannot even be destroyed safely at program termination. Thus, the old buffer should always be saved and restored later!
所以答案似乎是肯定的,虽然我没有标准的引述,但上面的作者是个专家。
在思考如何回答时, I noticed a link to an answer to a related SO post。我用 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;
}
构建程序的命令:
g++ -Wall -std=c++11 -g socc.cc -o socc
来自gdb
的输出:
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from socc...done.
(gdb) run
Starting program: /.........../socc (removed some text here)
Traceback (most recent call last):
File "/usr/share/gdb/auto-load/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19-gdb.py", line 63, in <module>
from libstdcxx.v6.printers import register_libstdcxx_printers
ImportError: No module named 'libstdcxx'
Program received signal SIGSEGV, Segmentation fault.
0x000000000040073c in ?? ()
(gdb) bt
#0 0x000000000040073c in ?? ()
#1 0x0000000000000000 in ?? ()
(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;
}
有了这个改动,程序运行就没有任何问题了。
我对 cerr
和 clog
进行了类似的实验,结果相同。
这让我想到以下问题:
如果 cout
、cerr
和 clog
已更改为重定向到文件,是否总是需要重置它们的 rdbuf
?
如果不是,这是 g++ 缺陷吗?
引自 The C++ Standard Library - A tutorial and reference Nicolai Josuttis 第 2 版,
通道。 2013 年 12 月 15 日,重定向标准流 第 822 页
...
std::cout.rdbuf (file.rdbuf());
Caution! The object
file
is local and is destroyed at the end of the block. This also destroys the corresponding stream buffer. This differs from the “normal” streams because file streams allocate their stream buffer objects at construction time and destroy them on destruction. Thus, in this example,cout
can no longer be used for writing. In fact, it cannot even be destroyed safely at program termination. Thus, the old buffer should always be saved and restored later!
所以答案似乎是肯定的,虽然我没有标准的引述,但上面的作者是个专家。