为什么我的缓冲区占用的字节数超过了允许的字节数
Why does my buffer take more bytes than allowed?
我将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"
}
首先,注意pubsetbuf
是实现定义的。在gcc上,它设置了一个新的缓冲区,但例如在MSVC上,什么都不发生(它调用基类setbuf
,它什么都不做)。
现在,如上所述,sputn
调用溢出(或通过其他方式实现调用溢出的效果):
如果放置区域变满(pptr()==epptr()),此函数可能调用overflow(),或者通过一些其他未指明的方式。
现在根据文档溢出:
确保放置区域至少有一个字符的空间通过保存从pbase()开始的一些初始字符子序列并更新指向输出区域的指针(如果需要)。如果ch不是tracts::eof()(即tracts:eq_int_type(c,traits::of())!=true),则将其放入输出区域或直接保存到输出序列。
该函数可以更新pptr、epptr和pback指针,以定义写入更多数据的位置。一旦出现故障,该功能将确保pptr()==nullptr或pptr(()==epptr。
基本上,这意味着可以适当地调整缓冲区的大小,以适应更多的数据,而对于gcc,这正是正在发生的事情。以下是从这里获得的实际代码:
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
的大小,直到达到字符串缓冲区可以达到的最大大小。
C/C++不做任何显式边界检查,因此溢出内存是可能的(而且很容易做到)。如果您通过像Valgrind这样的调试器运行代码,它会告诉您正在读取未初始化的内存。
您的缓冲区仍然有5个字节长,占用的字节数不会超过允许的字节数,但放入12个字节将"只是"执行边界外写入,这可能会导致软件编程中的许多问题(崩溃、UB、数据损坏…)
strlen
可以用于在复制之前根据缓冲区大小检查您所写的内容。
- 如何将字节数组元素替换为修改的十六进制 ASCII 符号?
- 基于字节数组生成静态范围整数值
- 在这种情况下,我真的复制了字节还是复制了字符?
- 将字节数组转换为带有字节序问题的指针
- 使用 stbi_write_png,如何将 0 和 1 的矩形字节数组转换为单色 png 文件?
- 字节数组初始化会导致 DirectX 崩溃
- 使用 swig 追加到字节数组
- C++ 替换字节数组中项的顺序
- QDataStream 读取和写入的字节数比 QFile::length() 报告要多
- 如何从保存在 Java 中C++的字节数组中读取数字?
- 如何在C++(Arduino)中将浮点数组转换为字节数组
- 将字节数组转换为多维数组
- 为什么 sizeof 在 C++ 中给出不正确的字节数?
- 如何将带有空字符的字节数组馈送到 std::iostream 中?
- C++字节数组到整数
- C RLE BMP压缩跳过了最后一个字节
- 在写入二进制文件时,ofstream::write写入的字节数超过了应有的字节数
- 为什么我的缓冲区占用的字节数超过了允许的字节数
- 移动字节数组和跳过位
- 很好地表示了字节数组及其大小