如果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?

本文关键字:是否 文件 重定向 cerr cout clog rdbuf 如果      更新时间:2023-10-16

在试图找出如何回答时https://stackoverflow.com/questions/33601384/what-is-the-file-descriptor-of-linuxs-environments-standard-logging-stream,我注意到一个链接,链接到一个相关SO帖子的答案。我用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;
}

有了这个更改,程序运行起来没有任何问题。

我用cerrclog进行了类似的实验,结果相同。

这引出了我的问题:

如果coutcerrclogrdbuf已更改为重定向到文件,是否总是需要重置它们?

如果不是,这是g++缺陷吗?

引用C++标准库-教程和参考第2版,作者:Nicolai Josuttis,

Ch。15.12.13,重定向标准流第822页

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

小心对象file是本地的,在块的末尾被销毁。这也破坏了相应的流缓冲区。这与"普通"流不同,因为文件流在构建时分配其流缓冲区对象,并在销毁时销毁它们。因此,在该示例中,cout不能再用于写入。事实上,它甚至不能在程序终止时安全地销毁。因此,旧的缓冲区应该始终保存并在以后恢复!

所以答案似乎是肯定的,尽管我没有一句标准的名言,但上面的作者是一位相当专业的人。

相关文章: