C++ stream to memory
Asked Answered
O

3

8

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.

Orthoptic answered 24/4, 2009 at 16:14 Comment(0)
P
8

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.

Peipus answered 24/4, 2009 at 16:17 Comment(6)
I'm curious about the down vote. Did someone have a problem with this solution?Peipus
don't suggest Boost. Many companies can't put Boost into their code. My own (Microsoft), included.Ytterbite
@ericfrazer boost is fine for many. No downvote needed because of it.Toll
it's not an answer. it's a library many don't want to include.Ytterbite
it's like being asked how to tune and engine and being told "buy a new car"Ytterbite
@ericfrazer this is the most upvoted answer, because it IS, an answer. It's not buy a new car, but buy an aftermarket part.Dzungaria
B
2
#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 
Boland answered 16/3, 2020 at 15:44 Comment(1)
See also: https://mcmap.net/q/448306/-a-custom-ostreamBoland
E
1

A minimal memory buffer has to implement only the overflow function of std::streambuf and keep track of the 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.

Excide answered 21/1, 2023 at 13:6 Comment(1)
Hey Stephan, apart from fixing a small typo, I removed that "get" from "get pointers" in my edit, but that may have been a mistake from me. (I was focusing on "output" etc., and got confused by that "get", or at least by "why only get"... I'm still kinda confused, honestly; I'm no iostream expert...) Would you prefer a rollback?Corri

© 2022 - 2024 — McMap. All rights reserved.