I am implementing my own streambuffer for output stream. Basically it is a vector-like streambuffer in which everytime the overflow function simply reallocates the buffer to two times larger. The sync function will write all data out to the device specified by a file descriptor fd.
class MyStreamBuf : public ::std::streambuf { constexpr static size_t INIT_BUFFER_SIZE {1024}; public: MyStreamBuf(); ~MyStreamBuf(); void fd(const int); int sync() override; int_type overflow(int_type ch = traits_type::eof()) override; private: int _fd {-1}; size_t _size; char_type* _base; void _resize(const size_t); }; MyStreamBuf::MyStreamBuf() { _size = INIT_BUFFER_SIZE; _base = static_cast<char_type*>(malloc(_size * sizeof(char_type))); setp(_base, _base + _size - 1); // -1 to make overflow easier. } // Destructor. MyStreamBuf::~MyStreamBuf() { ::free(_base); } // Procedure: fd // Change the underlying device. void MyStreamBuf::fd(const int fd) { _fd = fd; } // Procedure: _resize // Resize the underlying buffer to fit at least "tgt_size" items of type char_type. void MyStreamBuf::_resize(const size_t tgt_size) { // Nothing has to be done if the capacity can accommodate the file descriptor. if(_size >= tgt_size) return; // Adjust the cap to the next highest power of 2 larger than num_fds for(_size = (_size ? _size : 1); _size < tgt_size; _size *= 2); // Adjust and reset the memory chunk. _base = static_cast<char_type*>(::realloc(_base, _size*sizeof(char_type))); setp(_base, _base + _size - 1); // -1 to make overflow easier. } int MyStreamBuf::sync() { int res = 0; ::std::ptrdiff_t remain = pptr() - pbase(); while(remain) { issue_write: auto ret = ::write(_fd, pptr() - remain, remain); if(ret == -1) { if(errno == EINTR) { goto issue_write; } else if(errno == EAGAIN) { break; } else { res = -1; break; } } remain -= ret; } if(remain) { ::memcpy(pbase(), pptr() - remain, remain*sizeof(char_type)); } pbump(pbase() + remain - pptr()); return res; } typename MyStreamBuf::int_type MyStreamBuf::overflow(int_type ch) { assert(traits_type::eq_int_type(ch, traits_type::eof()) == false); _resize(_size * 2); return ch; } However I am getting segfault while replacing the cout with my own buffer. I couldn't find where the error is after struggling with GDB.
// Function: main int main() { auto fd = open("./test.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); MyStreamBuf d; d.fd(fd); ::std::cout.rdbuf(&d); ::std::cout << 1 << " " << 2 << ::std::endl; close(fd); return 0; } Is there anything wrong with this implementation? I saw many articles typically overriding sync and overflow are required.