我将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"
}
答案 0 :(得分:5)
首先,请注意pubsetbuf
是实现定义的。在gcc上它设置了一个新缓冲区,但是例如在MSVC上没有任何反应(它调用基本类setbuf
,它什么都不做)。
现在,如上所述[{3}},sputn
调用here(或通过其他方式实现调用它的效果):
如果put区域变满(pptr()== epptr()),则此函数可能 调用overflow(),或者实现一些调用overflow()的效果 其他,未指明,意味着。
现在根据overflow的文档:
确保至少一个字符的放置区域有空间 通过从pbase()开始保存一些字符的初始子序列 到输出序列并更新指向输出区域的指针 (如果需要的话)。如果ch不是traits :: eof()(即traits :: eq_int_type(c, traits :: eof())!= true),它被放到输出区域或 直接保存到输出序列。
该函数可以更新pptr,epptr和pback指针来定义 位置写入更多数据。失败时,该功能确保了这一点 pptr()== nullptr或pptr()== epptr。
基本上,这意味着可以适当调整缓冲区以适应更多数据,而使用gcc这正是发生的事情。这是实际代码overflow:
const __size_type __opt_len = std::max(__size_type(2 * __capacity), __size_type(512));
const __size_type __len = std::min(__opt_len, __max_size);
正如您所看到的那样,要么将容量加倍,要么将其设置为512
的大小,直到它达到字符串缓冲区可以达到的最大大小。
答案 1 :(得分:0)
C / C ++没有进行任何显式边界检查,因此可以溢出内存(并且很容易)。如果您通过像Valgrind这样的调试器运行代码,它会告诉您正在读取未初始化的内存。
答案 2 :(得分:-1)
你的缓冲区仍然是5个字节长,并且不会占用超过允许的字节数,但是输入12个字节将“只”执行写出边界,这可能会导致软件编程中的许多问题(崩溃,UB,数据损坏...)
在复制之前,可以使用 strlen
来检查您对缓冲区大小所写的内容。