2012-05-01 2 views
4

Это касается строк в C++. Я не касался C/C++ в течение очень долгого времени; infact Я занимался программированием на этих языках только в течение первого года обучения в колледже около 7 лет назад.Происходит ли переполнение буфера в строках C++?

В C для хранения строк мне приходилось создавать массивы символов (будь то статические или динамические, это не вызывает беспокойства). Таким образом, это означало бы, что мне нужно заранее угадать размер строки, которую будет содержать массив. Ну, я применил тот же подход в C++. Я знал, что существует класс std :: string, но я никогда не использовал его.

Вопрос в том, что, поскольку мы никогда не объявляем размер массива/строки в классе std :: string, происходит переполнение буфера при записи на него. Я имею в виду, что в C, если размер массива был 10, и я набрал более 10 символов на консоли, тогда дополнительные данные будут записываться в другое место памяти другого объекта, которое находится рядом с массивом. Может ли подобное происходить в std :: string при использовании объекта cin.

Должен ли я угадывать размер строки перед рукой на C++ при использовании std :: string?

Хорошо! Спасибо вам всем. На этой странице нет ни одного правильного ответа (много разных объяснений), поэтому я не выбираю ни одного такого как такового. Я доволен первым 5. Заботьтесь!

+0

Нет, не беспокойтесь. –

+0

Значит, мне не нужно угадывать размер строки перед рукой? – Jazz

ответ

1

Предполагая, что библиотека, предоставляющая std::string, правильно написана, вы не можете вызвать переполнение буфера, добавив символы в объект std::string.

Конечно, ошибки в библиотеке невозможны.

+1

Точнее (но я думаю, что ваш ответ - это то, что искал плакат), переполнение буфера будет проявляться с помощью исключения 'std :: bad_alloc', а не поврежденной памяти. И вам нужно будет создать довольно большую строку, чтобы это произошло. –

+0

Спасибо за ответ! – Jazz

6

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

Если, конечно, вы не ниспровергать методы доступа, что обеспечивает std::string, и сделать что-то вроде:

std::string str = "foo"; 
char *p = (char *)str.c_str(); 
strcpy(p, "blah"); 

У вас нет защиты здесь, и призываете неопределенное поведение.

+0

Значит, это только производные функции из C, которые могут вызвать проблемы? – Jazz

+0

@Jazz: Ну, в общем, он дает еще один пример в его ответе. –

+2

Без трансляции, по крайней мере, компилятор обнаружит несоответствие типа. Изменение указателя, возвращаемого 'const charT * c_str() const;' является UB. Это требование указано с помощью выражения 'c_str()': 'Требуется: программа не должна изменять какие-либо значения, хранящиеся в массиве символов. – dirkgently

2

В C++ класс std::string начинается с минимального размера (или вы можете указать начальный размер). Если этот размер превышен, std::string выделяет больше динамической памяти.

+0

Спасибо за ответ! – Jazz

3

std :: string обычно защищает от переполнения буфера, но все еще существуют ситуации, при которых ошибки программирования могут привести к переполнению буфера. В то время как C++ обычно генерирует исключение out_of_range, когда операция ссылается на память за пределами строки, , индексный оператор [] (который не выполняет проверку границ) не.

Другая проблема возникает при преобразовании std :: string объектов в строки стиля C. Если вы используете string :: c_str() для преобразования, вы получаете строку C-стиля с нулевым завершением. Однако, если вы используете string :: data(), который записывает строку непосредственно в массив (возвращая указатель на массив), вы получаете буфер, который не является нулевым. The only difference between c_str() and data() is that c_str() adds a trailing null byte.

Наконец, многие существующие программы и библиотеки C++ имеют свои собственные классы строк. Чтобы использовать эти библиотеки, вам, возможно, придется использовать эти типы строк или постоянно конвертировать туда и обратно. Такие библиотеки имеют различное качество, когда речь идет о безопасности.Как правило, лучше всего использовать стандартную библиотеку (когда это возможно) или понять семантику выбранной библиотеки. Вообще говоря, библиотеки должны оцениваться на основе того, насколько легко или сложно их использовать, типа ошибок, которые могут быть сделаны, насколько легко эти ошибки должны быть сделаны, и каковы могут быть возможные последствия. см https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/295-BSI.html

В C причина объясняется следующим образом:

void function (char *str) { 
     char buffer[16]; 
     strcpy (buffer, str); 
    } 
    int main() { 
     char *str = "I am greater than 16 bytes"; // length of str = 27 bytes 
     function (str); 
    } 

Эта программа гарантированно вызвать неожиданное поведение, так как строка (строка) из 27 байтов был скопирован в папку (буфер) который был выделен только для 16 байтов. Дополнительные байты проходят мимо буфера и перезаписывают пространство, выделенное для FP, адрес возврата и т. Д. Это, в свою очередь, искажает стек процесса. Функция, используемая для копирования строки, - это strcpy, которая не завершает проверку границ. Использование strncpy предотвратило бы это повреждение стека. Однако этот классический пример показывает, что переполнение буфера может перезаписать адрес возврата функции, что, в свою очередь, может изменить путь выполнения программы. Напомним, что обратный адрес функции - это адрес следующей инструкции в памяти, которая выполняется сразу после возвращения функции.

вот good tutorial, который может дать ваш ответ удовлетворительным.

+0

Но ОП задает вопрос о 'std :: string'. –

+0

@OliCharlesworth ya Я получил его, чтобы увидеть редактирование. Спасибо –

+0

Спасибо за ответ! – Jazz

7

В зависимости от участника (ов), который вы используете для доступа к объекту string, да. Так, например, если вы используете reference operator[](size_type pos), где pos > size(), да, вы бы это сделали.

+0

Спасибо за ответ! – Jazz

0

«Переполнение буфера происходит в коде на C++?»

В той степени, в которой программы на C являются законными C++-кодом (они почти все), а программы C имеют переполнение буфера, программы на C++ могут иметь переполнение буфера.

Будучи богаче, чем C, я уверен, что C++ может иметь переполнение буфера таким образом, что C не может: -}

Смежные вопросы