c++ - 在 C++ 中使用 cin 和 Width() 来避免缓冲区溢出

标签 c++ file io buffer-overflow

这是一个简单的问题。我写了这个 C++ 代码:

    char chaine[12];
    cin.width(12);
    cin >> chaine;

但是,如果我在运行时输入一些长度超过 12 个字符的文本,Visual Studio 会通知我堆栈现在已损坏。

据我所知,问题是缓冲区溢出。但我认为“宽度”方法可以防止这种情况。

如果宽度方法不能防止缓冲区溢出,有人可以向我解释一下它的作用是什么吗?我在网上搜索过,但没有找到任何东西。

谢谢!

最佳答案

这段代码确实显然应该将输入限制为 11 个字符(第 12 个字符用于终止空字符)。该标准在 27.7.2.2.3 [istream::extractors] 第 7 和 8 段中明确指出:

... If width() is greater than zero, n is width(). ... Characters are extracted and stored until any of the following occurs: - n-1 characters are stored; ...

我也用 gcc 尝试过,它显然只能读取 11 个字符。我不知道解决这个问题的最佳方法是什么。通常,我不会遇到这样的问题,因为我只是简单地读取 std::string 对象,这些对象可以根据需要增长。嗯,也有一些巨大的限制,我从来没有尝试过当超过这个限制时会发生什么。如果您绝对需要读入char数组,您可以做两件事:

  1. 您可以为 char 数组创建适配器并自行定义合适的输入运算符
  2. 您可以创建一个临时安装的过滤流缓冲区,它限制字符数或假装读取空格字符。

下面是有关如何执行后者的示例。创建适配器的技术实际上可以用于根据数组的大小自动设置宽度。

#include <iostream>
#include <cctype>

struct adaptor
{
    template <int Size>
    adaptor(char (&array)[Size]): it(array), end(array + Size - 1) {}
    mutable char*  it, * end;
};

std::istream& operator>> (std::istream& in, adaptor const& value)
{
    std::istreambuf_iterator<char> it(in), end;
    if (it == end)
    {
        in.setstate(std::ios_base::failbit);
    }
    for (; it != end && value.it != value.end && !std::isspace(static_cast<unsigned char>(*it));
         ++it, ++value.it)
    {
        *value.it = *it;
    }
    *value.it = 0;
    return in;
}

int main()
{
    char buffer[12];
    if (std::cin >> adaptor(buffer))
        std::cout << "read='" << buffer << "'\n";
    else
        std::cout << "input failed\n";
}

关于c++ - 在 C++ 中使用 cin 和 Width() 来避免缓冲区溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8766641/

相关文章:

c# - 如何使用httpwebrequest从网站拉取图片到本地文件

java - 如何获取计算机上的所有媒体文件

python - 使用 ndimage.binary_fill_holes 填充形状

c - fgetc() 在函数中无法正常工作

c++ - 专门用于任意类型 vector 的模板

java - 递归地将文件添加到 JList - 仅添加最后一个文件夹中的文件

c# - 局域网连接开启或关闭

C++程序——输入文本流

c++ - 在 C++ 中使用函数指针成员初始化结构数组

c++ - 我如何记录以便文档适用于类成员而不是匿名类型?