Использование динамически распределенных массивов вызывает предупреждение C6386 Buffer Overrun от анализа кода - PullRequest
0 голосов
/ 12 июля 2020

Когда я использую динамически выделяемый массив в C ++, я получаю C6386 предупреждение , выдаваемое анализом кода Visual Studio 2019.

Вот минимальный воспроизводимый пример:

#include <vector>

int main()
{
    std::vector<int> someInts{ 1, 2, 3 };

    int* dynamicInts = new int[someInts.size()];

    for (size_t i = 0; i < someInts.size(); i++)
    {
        dynamicInts[i] = someInts[i];
    }

    delete[] dynamicInts;
}

Смысл в том, что у нас есть вектор целых чисел, и мы хотим по какой-то причине скопировать их в динамически выделяемый массив целых чисел. (Немного глупый пример, но он показывает проблему). Он использует size() вектора во время выделения массива dynamicInts и в качестве верхней границы l oop, поэтому не должно быть проблем с переполнением буфера, которые я вижу.

Но этот код генерирует:

main.cpp(11): warning C6386: Buffer overrun while writing to 'dynamicInts':  the writable size is 'someInts.public: unsigned int __thiscall std::vector<int,class std::allocator<int> >::size(void)const ()*4' bytes, but '8' bytes might be written.

Подробное объяснение в Список ошибок объясняет это как:

7: 'dynamicInts' is an array of 1 elements (4 bytes)
9: Enter this loop. (assume 'i<someInts.size()')
9: 'i' may equal 1
9: Continue this loop. (assume 'i<someInts.size()')
11: 'i' is an In/Out argument to 'std::vector<int,std::allocator<int> >::[]'
11: Invalid to write to 'dynamicInts[1]'. (writable range is 0 to 0)

Эти сообщения предполагают, что анализатор считает, что массив dynamicsInts - это всего лишь один элемент.

Это кажется странным. Я знаю «Анализ кода сложен», , но, конечно же, у анализатора есть вся информация, необходимая для определения длины массива и привязки l oop?

Так это просто ложноотрицательный результат анализа кода? Или мне что-то не хватает?

Если это ложноотрицательный результат, то как лучше всего избежать этого предупреждения, не добавляя подавление и не предполагая, что нам нужно придерживаться динамически выделяемых массивов?

1 Ответ

0 голосов
/ 12 июля 2020

Интересно, что я могу убрать предупреждение go, введя бессмысленную промежуточную переменную для размера массива, например:

#include <vector>

int main()
{
    std::vector<int> someInts{ 1, 2, 3 };
    size_t numberOfInts = someInts.size();

    int* dynamicInts = new int[numberOfInts];

    for (size_t i = 0; i < numberOfInts; i++)
    {
        dynamicInts[i] = someInts[i];
    }

    delete[] dynamicInts;
}

Понятия не имею, почему это нравится Анализатору кода, но не нравится исходный код.

Анализатор также доволен, если я использую интеллектуальный указатель для хранения динамического c выделения, что немного аккуратнее и, вероятно, так, как это должно было быть написано в первое место.

#include <vector>
#include <memory>

int main()
{
    std::vector<int> someInts{ 1, 2, 3 };

    std::unique_ptr<int[]> dynamicInts(new int[someInts.size()]);

    for (size_t i = 0; i < someInts.size(); i++)
    {
        dynamicInts[i] = someInts[i];
    }
}
...