While trying to figure out how to answer https://stackoverflow.com/questions/33601384/what-is-the-file-descriptor-of-linuxs-environments-standard-logging-stream, I noticed a link to an answer to a related SO post. I tried the code in the above linked answer with g++ 4.8.4 and got segmentation error before the program terminated.
Here's the program:
#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;
}
The command to build the program:
g++ -Wall -std=c++11 -g socc.cc -o socc
Output from 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)
I updated the program to keep the old rdbuf
of cout
and reset it before the end of the program.
#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;
}
With this change, the program ran without any problem.
I experimented similarly with cerr
and clog
with identical results.
That leads me to the questions:
Is it always necessary to reset rdbuf
of cout
, cerr
, and clog
if they have been changed to be redirected to a file?
If not, is this a g++ defect?
Citing from The C++ Standard Library - A tutorial and reference 2nd edition by Nicolai Josuttis,
Ch. 15.12.13, Redirecting Standard Streams pp. 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!
So the answer seems to be Yes, and even though I don't have a standard quote, the author above is quite an expert.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With