为什么我的缓冲区占用的字节数多于允许的数

时间:2013-06-27 20:59:27

标签: c++ file iostream

我将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"
}

3 个答案:

答案 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来检查您对缓冲区大小所写的内容。