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

mil*_*bug 9 c++ buffer iostream overflow

如果我使用std :: CIN,性病::法院和std ::字符串,是否有任何可能有人会利用缓冲区溢出?

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

cHa*_*Hao 14

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

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

标准字符串和流被设计为溢出抗性,并且全能比字符指针(至少当他们没有安全使用像一个普通的旧阵列/指针;一味使用str的迭代,而不考虑用于str.end()通常是一个坏主意,但是str.push_back(),str += "text",str.at(x),和流插入/拔出运营商是绝对安全的).如果你可以使用它们,我强烈建议你这样做.


Alo*_*ave 12

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

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

这是非常安全的,您应该尽可能std::string在c ++中使用它.

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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

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

  • "这是非常安全的" - 根本不是真的,请参阅下面的例子.`std :: string`是安全的,如果你避免访问它超出范围,但那么C风格的字符串也是如此.不同之处在于你不太可能需要用`string`来担心它,但可能性不是零. (2认同)

seh*_*ehe 4

这取决于。当然,当您使用 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
Run Code Online (Sandbox Code Playgroud)

安全变体:

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
Run Code Online (Sandbox Code Playgroud)

  • `std::vector v();` 这看起来很令人烦恼。 (3认同)
  • 嗯,我不确定结论。如果您正确使用所有内容,那么唯一可能的错误应该是分配错误,这些错误通过异常发出信号。所以你不应该需要*任何*类型的“如果”和“但是”。不过,如果您的程序在只有 4GB 物理 RAM 的机器上请求 20GB,那么该程序仍然完全正确,但可能会迫使操作系统崩溃。但这超出了“安全编程”的范围。 (3认同)