Reputation: 4060
I set the buffer of my stringstream
to a 5 byte buffer. Only when I call sputn
it can read in more characters than I want. Why is this?
#include <iostream>
#include <sstream>
int main()
{
std::stringstream ss;
char buf[5];
ss.rdbuf()->pubsetbuf(buf, sizeof buf);
ss.rdbuf()->sputn("hello world", 12);
std::cout << ss.rdbuf(); // prints "Hello world"
}
Upvotes: 0
Views: 417
Reputation: 52365
First, note that pubsetbuf
is implementation defined. On gcc it sets a new buffer, but for example on MSVC nothing happens (it calls the base class setbuf
which does nothing).
Now, as mentioned here, sputn
calls overflow (or achieves the effect of calling it by some other means):
If the put area becomes full (pptr() == epptr()), this function may call overflow(), or achieve the effect of calling overflow() by some other, unspecified, means.
Now according to the docs for overflow:
Ensures that there is space at the put area for at least one character by saving some initial subsequence of characters starting at pbase() to the output sequence and updating the pointers to the output area (if needed). If ch is not traits::eof() (i.e. traits::eq_int_type(c, traits::eof()) != true), it is either put to the output area or directly saved to the output sequence.
The function may update pptr, epptr and pback pointers to define the location to write more data. On failure, the function ensures that either pptr() == nullptr or pptr() == epptr.
Basically, what this means is that is may resize the buffer appropriately to fit more data, and with gcc this is exactly what is happening. Here is the actually code take from here:
const __size_type __opt_len = std::max(__size_type(2 * __capacity), __size_type(512));
const __size_type __len = std::min(__opt_len, __max_size);
As you can see it either doubles the capacity or sets it to a size of 512
until it hits the maximum size the string buffer can reach.
Upvotes: 5
Reputation: 1345
C/C++ does not do any explicit bounds checking, so overflowing memory is possible (and easy to do). If you run your code through a debugger like Valgrind, it will tell you that you are reading uninitialized memory.
Upvotes: 0
Reputation: 8469
Your buffer is still 5 bytes long and doesn't take more byte than allowed, but putting 12 bytes in will "just" perform a write out of boundary that can cause a lot of issue in software programming (crash, UB, data corruption...)
strlen
may be use to check what you write against the buffer size before copying.
Upvotes: -1