Trying to override streambuf to use with cout

This is a discussion on Trying to override streambuf to use with cout within the C++ Programming forums, part of the General Programming Boards category; Hi,
I'm trying to grab all the input sent to cout to modify and redirect it. I used the example ...

The basic_xor_filter class overrides streambuf and simply XORs the input characters before sending them to the provided streambuf (in this case, a file). My problem occurs when I try setting cout's rdbuf() to filter:

Code:

streambuf* s = &filter;
cout.rdbuf( s );
cout << "Hello World\n";

This code causes a glibc "double free or corruption (!prev)" error. Could anyone tell me where I am going wrong? Perhaps I just don't understand the concepts properly?

Thanks for the reply CornedBeef, unfortunatley this hasn't solved the problem. I have managed to stop the glibc error by using std::endl instead of \n, but it is simply replaced with a seg fault. My code now looks like this:

This works normally for me. Without restoring the original streambuf debugger indicated a segfault in the global destructors - possibly the destructor of cout is trying to delete the streambuf (filter) which already went out of scope.

Thanks for the replies everyone, i think the issues I was having were caused by the example code, I stripped out everything I didn't need and now it works.

For anyone interested here is an example that works fine for me. It it basically designed to grab anything sent to cout and lets you do whatever you want with it at the line marked "//Do something with the string".

mystreambuf.h

Code:

#ifndef __MYSTREAMBUF_H
#define __MYSTREAMBUF_H
template <typename charT, typename traits = std::char_traits<charT> >
class mystreambuf : public std::basic_streambuf<charT, traits>
{
public:
// The size of the input and output buffers.
static const size_t BUFF_SIZE = 1024;
typedef traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
// You can use any method that you want, but here, we'll just take in a raw streambuf as a
// slave I/O object. xor_char is what each character is xored with before output.
explicit mystreambuf()
: out_buf_(new charT[BUFF_SIZE])
{
// Initialize the put pointer. Overflow won't get called until this buffer is filled up,
// so we need to use valid pointers.
this->setp(out_buf_, out_buf_ + BUFF_SIZE - 1);
}
// It's a good idea to release any resources when done using them.
~mystreambuf() {
delete [] out_buf_;
}
protected:
// This is called when there are too many characters in the buffer (thus, a write needs to be performed).
virtual int_type overflow(int_type c);
// This is called when the buffer needs to be flushed.
virtual int_type sync();
private:
// Output buffer
charT* out_buf_;
};
#endif

mystreambuf.cpp

Code:

// Based on class by perfectly.insane from http://www.dreamincode.net/code/snippet2499.htm
#include <fstream>
#include <iostream>
#include <streambuf>
#include "mystreambuf.h"
// This function is called when the output buffer is filled.
// In this function, the buffer should be written to wherever it should
// be written to (in this case, the streambuf object that this is controlling).
template <typename charT, typename traits>
typename mystreambuf<charT, traits>::int_type
mystreambuf<charT, traits>::overflow(mystreambuf<charT, traits>::int_type c)
{
charT* ibegin = this->out_buf_;
charT* iend = this->pptr();
// Reset the put pointers to indicate that the buffer is free
// (at least it will be at the end of this function).
setp(out_buf_, out_buf_ + BUFF_SIZE + 1);
// If this is the end, add an eof character to the buffer.
// This is why the pointers passed to setp are off by 1
// (to reserve room for this).
if(!traits_type::eq_int_type(c, traits_type::eof())) {
*iend++ = traits_type::to_char_type(c);
}
// Compute the write length.
int_type ilen = iend - ibegin;
//Do something with the string
printf("String: %.*s\n", ilen, out_buf_);
return traits_type::not_eof(c);
}
// This is called to flush the buffer.
// This is called when we're done with the file stream (or when .flush() is called).
template <typename charT, typename traits>
typename mystreambuf<charT, traits>::int_type
mystreambuf<charT, traits>::sync()
{
return traits_type::eq_int_type(this->overflow(traits_type::eof()),
traits_type::eof()) ? -1 : 0;
}
int main() {
mystreambuf<char> filter;
/*
std::ostream output_stream(&filter);
output_stream << "hello world";
output_stream.flush();
*/
std::streambuf* s = std::cout.rdbuf();
std::cout.rdbuf( &filter );
std::cout << "Hello World";
std::cout.flush();
std::cout.rdbuf(s);
}