0

我将我的缓冲区设置stringstream为 5 字节缓冲区。只有当我调用sputn它时,它才能读取比我想要的更多的字符。为什么是这样?

#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"
}
4

3 回答 3

5

首先,请注意这pubsetbuf是实现定义的。在 gcc 上它设置了一个新的缓冲区,但例如在 MSVC 上什么都没有发生(它调用什么都不做的基类setbuf)。

现在,如这里所说,sputn调用overflow(或通过其他方式达到调用的效果):

如果 put 区域已满(pptr() == epptr()),该函数可能会调用 overflow(),或者通过其他未指定的方式实现调用 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.

于 2013-06-27T21:31:46.463 回答
0

C/C++ 不做任何显式的边界检查,所以内存溢出是可能的(而且很容易做到)。如果您通过 Valgrind 之类的调试器运行代码,它会告诉您正在读取未初始化的内存。

于 2013-06-27T21:04:24.837 回答
-1

您的缓冲区仍然是 5 个字节长,并且不会占用超过允许的字节数,但是放入 12 个字节将“只是”执行可能导致软件编程出现很多问题的边界写入(崩溃、UB、数据损坏。 ..)

strlen可用于在复制之前检查您写入的内容与缓冲区大小的对比。

于 2013-06-27T21:08:38.843 回答