Почему VS выдаёт предупреждение C6386 (переполнение буфера)?
#include <iostream>
struct String
{
public:
String();
String(const char *str);
String(const String& str);
void print();
~String();
String& operator=(const String& other);
String operator+(const String& other);
private:
char *str;
int lenght;
};
String::String()
{
this->str = nullptr;
lenght = 0;
}
String::String(const char *str)
{
lenght = strlen(str);
this->str = new char[lenght + 1];
for(int i = 0; i < lenght; i++)
{
this->str[i] = str[i];
}
this->str[lenght] = '\0';
}
String::String(const String& other)
{
lenght = other.lenght;
this->str = new char[lenght + 1];
for (int i = 0; i < lenght; i++)
{
this->str[i] = other.str[i];
}
this->str[other.lenght] = '\0';
}
void String::print()
{
std::cout << str;
}
String::~String()
{
delete[] this->str;
this->str = nullptr;
}
String& String::operator=(const String& other)
{
if (this->str != nullptr)
{
delete[] str;
str = nullptr;
}
lenght = other.lenght;
this->str = new char[lenght + 1];
for (int i = 0; i < lenght; i++)
{
this->str[i] = other.str[i];
}
this->str[other.lenght] = '\0';
return *this;
}
String String::operator+(const String& other)
{
String NewStr;
NewStr.lenght = this->lenght + other.lenght;
NewStr.str = new char[NewStr.lenght + 1];
int i = 0;
for (;i < this->lenght; i++)
{
NewStr.str[i] = this->str[i];
}
for (int j = 0; j < other.lenght; j++, i++)
{
NewStr.str[i] = other.str[j];//предупреждение в этой строке
}
NewStr.str[NewStr.lenght] = '\0';
return NewStr;
}
int main()
{
String a("Hello");
String b("lello");
String c;
c = a + b;
c.print();
}
При замене
NewStr.lenght = this->lenght + other.lenght;
NewStr.str = new char[NewStr.lenght + 1];
На
NewStr.lenght = this->lenght + other.lenght;
NewStr.str = new char[this->lenght + other.lenght + 1];
Предупреждение пропадает
Ответы (1 шт):
Анализ кода человеком весьма "творческий" процесс. Человек может увидеть, как именно NewStr.lenght связан с this->lenght и other.lenght. Но заложить все возможные паттерны анализа в алгоритм не реально. Конкретно здесь анализатор кода не увидел/не просчитал эту зависимость. Но его предположение хоть и ошибочное, но хорошее с точки зрения последовательности изложения мысли программиста в коде. Посмотрите на свой код, можно сказать, что второй цикл - это продолжение первого, но с несколько изменившимся телом. Но алгоритм это не прочитал. Изменения затронули не только тело, но и счётчик. Итерируемся мы в обоих циклах по NewStr.str, а счетчиком для него служит i. Сейчас же для анализатора это два несвязанных цикла: первый по NewStr и this со счётчиком i, второй по NewStr и other со счётчиками i и j. Замените
for (int j = 0; j < other.lenght; j++, i++)
на
for (int j = 0; i < NewStr.lenght; j++, i++)
Теперь оба цикла связаны условием по i, инкрементом i, и итерированием через i по NewStr.str. Так более логично.
И самое интересное - предупреждение пропадает.