C ++字符串和流缓冲区溢出是否安全?

时间:2011-11-04 20:27:01

标签: c++ overflow buffer iostream

如果我使用std :: cin,std :: cout和std :: string,是否有任何可能会有人利用缓冲区溢出?

我问这个是因为我仍然看到很多人在C ++中仍然使用以null结尾的字符串而不是标准容器。

4 个答案:

答案 0 :(得分:14)

你仍然看到人们在C ++中使用C字符串的一个重要原因(除了不知道字符串,或者被卡在C语境中),std::istream::getline使用char指针而不是字符串。和图书馆的其他部分一样。部分原因是“你不为你不使用的东西买单”。 IE:只想获得一行文本的人不应该实例化string(因此也必须引入另一个模板类)才能这样做。如果需要,可以使用std::getline将行作为字符串获取,但这并不明显。所以有些人认为他们仍然需要使用char缓冲区来获取一行文本。

(似乎很多内容在C ++ 11中有所改变,你可以在很多地方使用string s,之前你必须通过char*。也许这会有所帮助有点C-in-C ++问题。)

标准字符串和流被设计为防溢出的,并且比char指针更安全(至少当它们不像那样使用像普通的旧数组/指针一样;盲目地使用str的迭代器而不考虑str.end()通常是一个坏主意,但str.push_back()str += "text"str.at(x)和流插入/提取运算符是完美的安全)。如果你可以使用它们,我强烈建议你这样做。

答案 1 :(得分:12)

仍有很多人使用以null结尾的字符串,因为他们没有意识到使用std::string的便利性,他们真的在编写程序性的c ++而不是c ++。

大多数从c迁移/迁移到c ++的程序员仍然使用以null结尾的字符串。

这是非常安全的,你应该在c ++中使用std::string

std:string实际上可以保护您免受缓冲区溢出(与c字符串不同),因为随着添加到其中的数据的增加,动态增长。

code sample

#include <iostream>
using namespace std;

int main()
{
    string str("std::String");
    for (int i=0; i<20; ++i)
    {
        cout << "capacity is " << str.capacity() << endl;
        str += " ,is Overrun safe string";
    }
    return 0;
}

输出:

  

容量为11
  容量是35
  容量是70
  容量是140
  容量是140
  容量是140
  容量是280
  容量是280
  容量是280
  容量是280
  容量是280
  容量是280
  容量是560
  容量是560
  容量是560
  容量是560
  容量是560
  容量是560
  容量是560
  容量是560

答案 2 :(得分:3)

这取决于。当然,当你使用C风格的代码/ API时,没有区别

但使用STL或C ++习语并不能保证你的安全。

C ++始终为您提供选择。对比这两个近乎完全相同的双胞胎:

int n;
std::cin >> n;
std::string s(n, '*'); // create a data store of given size

std::vector<char> v(1000);
std::copy(s.begin(), s.end(), v.begin()); // NOT safe if n > 1000

安全变体:

int n;
std::cin >> n;
if (n > MAX_LIMIT) 
    throw std::runtime_error("input too large");
std::string s(std::min(0, n), '*'); // note input sanitation

std::vector<char> v;
v.reserve(1000);
std::copy(s.begin(), s.end(), std::back_inserter(v)); // safe

答案 3 :(得分:1)

C字符串可能更快,因为std容器必须支持它们支持的某些功能。所以,没有人能够一直指出最佳选择。