# V1023. A pointer without owner is added to the container by the 'emplace_back' method. A memory leak will occur in case of an exception.

Анализатор обнаружил код добавления в контейнер умных указателей с помощью 'emplace_back(new X)'. Этот код может привести к утечке памяти.

Пример:

    std::vector<std::unique_ptr<int>> pointers;
    pointers.emplace_back(new int(42));

В случае, если вектору понадобится реаллокация и он не сможет выделить память под новый массив, то он бросит исключение и указатель будет потерян.

Корректный код:

    pointers.push_back(std::unique_ptr<int>(new int(42)));
    pointers.push_back(std::make_unique<int>(42));

Давайте разберёмся с этим видом ошибки более подробно.

Для добавлении элемента в конец контейнера типа 'std::vector<std::unique_ptr<X>>' нельзя просто написать 'v.push_back(new X)', так как нет неявного преобразования из 'X*' в 'std::unique_ptr<X>'.

Распространенным решением является написание 'v.emplace_back(new X)', так как он компилируется: метод 'emplace_back' конструирует элемент непосредственно из аргументов и поэтому может использовать явные конструкторы.

Тем не менее, это не безопасно. Если вектор полон, то происходит перевыделение памяти. Операция перевыделения памяти может закончиться неудачей, в результате чего будет сгенерировано исключение 'std::bad_alloc'. В этом случае указатель будет потерян, и созданный объект никогда не будет удален.

Безопасным решением является создание 'unique_ptr', который будет владеть указателем до того, как вектор попытается перевыделить память:

    v.push_back(std::unique_ptr<X>(new X))

Начиная с C++14 можно использовать 'std::make_unique':

    v.push_back(std::make_unique<X>())

Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки утечек памяти, незакрытых файловых дескрипторов и дескрипторов сетевых соединений [* см. примечание касательно языков C#, Java].

Данная диагностика классифицируется как:

CWE-460 CERT-ERR56-CPP

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V1023.