Безопасно ли переполнение буфера строк и потоков C ++? - PullRequest
9 голосов
/ 05 ноября 2011

Если я использую std :: cin, std :: cout и std :: string, есть ли любая вероятность того, что кто-то воспользуется переполнением буфера?

Я спрашиваю это, потому что явсе еще видят много людей, которые все еще используют строки с нулевым символом в конце вместо стандартных контейнеров в C ++.

Ответы [ 4 ]

14 голосов
/ 05 ноября 2011

Одна из главных причин, по которой вы все еще видите людей, использующих C-строки в C ++ (помимо незнания о строках или застревания в мышлении C), заключается в том, что std::istream::getline работает с указателями на символы, а не на строки. Как и огромное количество других частей библиотеки. Одной из причин этого было то, что «вы не платите за то, что не используете». IE: люди, которые просто хотят получить строку текста, не должны создавать экземпляр string (и, следовательно, также должны использовать другой класс шаблона), чтобы сделать это. Вы можете использовать std::getline, чтобы получить строки в виде строк, если хотите, но это не очевидно. Поэтому некоторые люди думают, что им все еще нужно использовать буферы символов для получения строки текста.

(Кажется, многое изменилось в C ++ 11, и вы можете использовать string s во многих местах, где раньше вам приходилось пропускать char*. Возможно, это немного поможет с Проблема C-in-C ++.)

Стандартные строки и потоки предназначены для защиты от переполнения и более безопасны, чем указатель на символ (по крайней мере, когда они не используются как обычный старый массив / указатель; использование вслепую Итератор str без учета str.end() обычно является плохой идеей, но str.push_back(), str += "text", str.at(x) и операторы вставки / извлечения потока совершенно безопасны). Если вы можете использовать их, я настоятельно рекомендую вам сделать это.

12 голосов
/ 05 ноября 2011

Тем не менее, многие люди используют строки с нулевым символом в конце, потому что они не осознают удобство использования std::string и действительно пишут процедурный c ++, а не c ++.

Большинство программистов, мигрирующих / мигрировавших с c на c ++, являются теми, кто все еще использует строки с нулевым символом в конце.

Это совершенно безопасно, и вы должны использовать 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;
}

Выход:

емкость составляет 11
емкость составляет35
емкость 70
емкость 140
емкость 140
емкость 140
емкость 280
емкость 280
емкость 280
емкость 280
емкость 280
емкость 280
емкость 560
емкость 560
емкость 560
емкость 560
емкость 560
емкость 560
емкость 560
емкость 560

3 голосов
/ 05 ноября 2011

Это зависит. Конечно, когда вы используете код / ​​API в стиле C, не имеет значения .

Но использование идиом 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
1 голос
/ 05 ноября 2011

C-строки могут быть быстрее, потому что std-контейнеры должны поддерживать некоторые функции, которые они поддерживают.Так что никто не может указать лучший выбор на все времена.

...