如果我使用std :: cin,std :: cout和std :: string,是否有任何可能会有人利用缓冲区溢出?
我问这个是因为我仍然看到很多人在C ++中仍然使用以null结尾的字符串而不是标准容器。
答案 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字符串不同),因为随着添加到其中的数据的增加,动态增长。
#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容器必须支持它们支持的某些功能。所以,没有人能够一直指出最佳选择。