Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top

Вебинар: Использование статических анализаторов кода при разработке безопасного ПО - 19.12

>
>
>
V824. It is recommended to use the 'mak…
menu mobile close menu
Проверка проектов
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Микрооптимизации (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Реализовано по запросам пользователей (C++)
Cтандарт MISRA
Стандарт AUTOSAR
Стандарт OWASP (C++)
Стандарт OWASP (C#)
Проблемы при работе анализатора кода
Дополнительная информация
toggle menu Оглавление

V824. It is recommended to use the 'make_unique/make_shared' function to create smart pointers.

02 Июн 2020

Анализатор рекомендует создать умный указатель не путем вызова конструктора, принимающего "сырой" указатель на ресурс, а вызовом функции 'make_unique' / 'make_shared'.

Использование этих функций позволяет:

  • улучшить читаемость кода, устраняя явные вызовы оператора 'new' для динамических аллокаций (сами умные указатели устраняют явный вызов оператора 'delete');
  • повысить безопасность кода в случае броска исключения;
  • может оптимизировать размещение объектов в памяти.

Рассмотрим пример кода:

void foo(std::unique_ptr<int> a, std::unique_ptr<int> b)
{
  ....
}

void bar()
{
  foo( std::unique_ptr<int> { new int { 0 } },
       std::unique_ptr<int> { new int { 1 } });
}

Поскольку стандартом не регламентируется порядок вычисления аргументов функции, компилятор в целях оптимизации может сделать это в такой последовательности:

  • Вызов 'new int { 0 }'
  • Вызов 'new int { 1 }'
  • Первый вызов конструктора 'std::unique_ptr<int>'
  • Второй вызов конструктора 'std::unique_ptr<int>'

В этом случае, если второй вызов 'new' бросит исключение, произойдет утечка памяти – ресурс, выделенный первым вызовом 'new', никогда не будет освобожден. Создание указателя при помощи 'make_unique' решает эту проблему, гарантируя освобождение памяти в случае броска исключения.

Оптимизированный код:

void foo(std::unique_ptr<int> a, std::unique_ptr<int> b)
{
  ....
}

void bar()
{
  foo( std::make_unique<int>(0), std::make_unique<int>(1));
}

Начиная с C++17, хотя порядок вычисления аргументов остается неуточненным, вводятся дополнительные гарантии. Все побочные эффекты от аргумента функции должны быть вычислены до того, как произойдет вычисление следующего аргумента. Это снижает риски в случае исключений, но использовать 'make_unique' все равно предпочтительно.

Замечание по поводу 'make_shared'. При использовании этой функции контрольный блок указателя размещается в памяти рядом с объектом. Это уменьшает количество динамических аллокаций и оптимизирует использование кэша процессора.

Объект удаляется, когда счетчик ссылок становится нулевым, но контрольный блок существует до тех пор, пока существуют слабые ссылки на указатель. Если контрольный блок и объект были созданы при помощи 'make_shared' (т.е. размещены в одной области памяти), это приводит к тому, что память не может быть освобождена до тех пор, пока счетчик ссылок нулевой и на объект ссылается хотя бы один 'weak_ptr'. Для больших объектов такое поведение может быть нежелательным. Если функция 'make_shared' не используется сознательно, чтобы избежать размещения контрольного блока в одной области памяти с объектом, срабатывание диагностики можно подавить.

Ограничение, связанное с разными версиями стандарта C++: так как возможности функций 'make_unique' и 'make_shared' менялись, начиная с C++11, диагностика зависит от версии стандарта следующим образом:

  • C++11: анализатор предлагает заменять аллокацию объекта и его последующую передачу в конструктор 'shared_ptr' на функцию 'make_shared'.
  • C++14 или выше: анализатор дополнительно предлагает заменять аллокацию одного объекта или массива объектов на функцию 'make_unique'.
  • C++20 или выше: анализатор дополнительно предлагает заменить конструктор 'shared_ptr' на функцию 'make_shared' также и для массива объектов.

close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

Шаг 2
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности
close form
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Бесплатная лицензия PVS‑Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
check circle
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте, отфильтровано ли письмо в одну из следующих стандартных папок:

  • Промоакции
  • Оповещения
  • Спам