all. I am using a slightly-modified version of the class defined at https://stackoverflow.com/a/1761027/2909854 which allows me to combine streams so that anything sent to the combined stream goes to all of the linked streams. This code works well for except for two issues:
- It causes
deprecated-declarations
warnings (that answer is from 2009). - If I inherit a
CombinedStream
object, when I use it, I get a segmentation fault.
Code:
#include <iostream>
// Needed for ComposeStream
#include <algorithm>
#include <vector>
#include <fstream>
#include <functional>
// A class that allows us to combine streams so that anything sent to the combined stream goes to all of them
// Modified from https://stackoverflow.com/a/1761027/2909854
class CombinedStream: public std::ostream
{
struct ComposeBuffer: public std::streambuf
{
void addBuffer(std::streambuf* buf)
{
bufs.push_back(buf);
}
virtual int overflow(int c)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
std::for_each(bufs.begin(),bufs.end(),std::bind2nd(std::mem_fun(&std::streambuf::sputc),c));
#pragma GCC diagnostic pop
return c;
}
private:
std::vector<std::streambuf*> bufs;
};
ComposeBuffer myBuffer;
public:
CombinedStream(): std::ostream(NULL)
{
std::ostream::rdbuf(&myBuffer);
}
void linkStream(std::ostream& out)
{
out.flush();
myBuffer.addBuffer(out.rdbuf());
}
};
class Parent
{
public:
Parent();
protected:
std::fstream m_outputFile;
CombinedStream m_outputFileAndCout;
};
class Child: protected Parent
{
public:
Child();
};
Parent::Parent()
{
std::string filePath = "test_file.test";
std::cout << "Opening " << filePath << "\n\n";
std::fstream m_outputFile(filePath, std::ios::app);
// Create a stream that combines cout and the process log
m_outputFileAndCout.linkStream(std::cout);
m_outputFileAndCout.linkStream(m_outputFile);
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
m_outputFileAndCout << "I'm working!" << std::endl;
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
}
Child::Child()
{
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
m_outputFileAndCout << "I'm crashing!" << std::endl;
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
}
int main()
{
Child object;
return 0;
}
Compilation:
g++-13 inherited_stream.cpp -o inherited_stream.exe -std=c++20 -g
Questions:
- Is it likely that the issues being pointed to by the
deprecated-declarations
warnings is causing this issue? If so, can you help me update thestd::for_each...
line to resolve these? - If no to question 1, any ideas why I get the segmentation fault?
Here is a gdb
backtrace:
(gdb) run
Starting program: /home/trackingtech/gateway/experiments/inherited_stream.exe
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
Opening test_file.test
inherited_stream.cpp:72
I'm working!
inherited_stream.cpp:74
inherited_stream.cpp:79
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x0000aaaaaaaa46a4 in std::mem_fun1_t<int, std::basic_streambuf<char, std::char_traits<char> >, char>::operator() (this=0xffffffffed60, __p=0xffffffffecd8, __x=73 'I') at /usr/include/c++/13/bits/stl_function.h:1309
#2 0x0000aaaaaaaa416c in std::binder2nd<std::mem_fun1_t<int, std::basic_streambuf<char, std::char_traits<char> >, char> >::operator() (this=0xffffffffed60, __x=@0xaaaaaaacc8d8: 0xffffffffecd8)
at /usr/include/c++/13/backward/binders.h:165
#3 0x0000aaaaaaaa38c8 in std::for_each<__gnu_cxx::__normal_iterator<std::basic_streambuf<char, std::char_traits<char> >**, std::vector<std::basic_streambuf<char, std::char_traits<char> >*, std::allocator<std::basic_streambuf<char, std::char_traits<char> >*> > >, std::binder2nd<std::mem_fun1_t<int, std::basic_streambuf<char, std::char_traits<char> >, char> > > (__first=0xffffffffecd8, __last=0x0, __f=...) at /usr/include/c++/13/bits/stl_algo.h:3833
#4 0x0000aaaaaaaa2cdc in CombinedStream::ComposeBuffer::overflow (this=0xfffffffff158, c=73) at inherited_stream.cpp:23
#5 0x0000fffff7e9f5b4 in std::basic_streambuf<char, std::char_traits<char> >::xsputn(char const*, long) () from /lib/aarch64-linux-gnu/libstdc++.so.6
#6 0x0000fffff7e9159c in std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) ()
from /lib/aarch64-linux-gnu/libstdc++.so.6
#7 0x0000fffff7e91950 in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) () from /lib/aarch64-linux-gnu/libstdc++.so.6
#8 0x0000aaaaaaaa29b8 in Child::Child (this=0xffffffffef38) at inherited_stream.cpp:80
#9 0x0000aaaaaaaa2a50 in main () at inherited_stream.cpp:86
(gdb)