7

how can I create std::ostream and std::istream objects to point to a piece of memory I allocated and manage (I don't want the stream to free my memory).

I was looking at using rdbuf()->pubsetbuf() to modify one of the other streams - say sstringstream. However I think streambuf used by stringstream will free the buffer afterwards?

Basically I'm trying to serialize some things to shared memory.

Thanks.

ilya1725
  • 4,496
  • 7
  • 43
  • 68
Budric
  • 3,599
  • 8
  • 35
  • 38

3 Answers3

9

Take a look at the bufferstream class in the Boost.Interprocess library:

The bufferstream classes offer iostream interface with direct formatting in a fixed size memory buffer with protection against buffer overflows.

Judge Maygarden
  • 26,961
  • 9
  • 82
  • 99
1
#include <iostream>
#include <streambuf>

//...
size_t length = 100;
auto pBuf = new char[length]; // allocate memory

struct membuf: std::streambuf // derive because std::streambuf constructor is protected
{
   membuf(char* p, size_t size) 
   {
       setp( p, p + size); // set start end end pointers
   }
   size_t written() {return pptr()-pbase();} // how many bytes were really written?
};

membuf sbuf( pBuf, length ); // our buffer object
std::ostream out( &sbuf );   // stream using our buffer

out << 12345.654e10 << std::endl;
out.flush();

std::cout << "Nr of written bytes: " << sbuf.written() << std::endl;
std::cout << "Content: " << (char*)pBuf << std::endl;

//...
delete [] pBuf; // free memory 
ilya1725
  • 4,496
  • 7
  • 43
  • 68
Joachim
  • 891
  • 9
  • 12
0

A minimal memory buffer has to implemented only the overflow function of std::streambuf and keep track of the get pointers of the streambuf. This is done via setp and pbump.

You will also need to add an underlying memory buffer, but this can be done rather easy. cppreference.com has a good example of an implementation based on an std::array in the already mentioned page for the overflow function. While this is a good start to learn, you might want to have a memory buffer that can resize. You can try to implement it based on an std::vector (like I did here).

I ended up writing a memory buffer based on std::realloc to get the most performance while also giving me the possibility to hand the raw pointer over to C libaries. You can find my implementation here.