Всё больше проектов появляется на Unreal Engine — от великого "Ведьмака" до не менее великой "The Day Before". И чем больше проект, тем выше цена одной незамеченной ошибки. Когда число строк кода переваливает за несколько тысяч, даже самый внимательный разработчик может не заметить неочевидный баг. И тут на помощь приходит он — PVS-Studio, который помогает снизить риск попадания багов в ваши UE-проекты.

Введение
В gamedev происходит постоянная борьба разработчиков с багами и, к сожалению, полностью избавиться от ошибок остаётся недостижимой мечтой. Но программисты не сдаются и продолжают искать эффективные способы выявления уязвимостей в коде, опираясь на разнообразные инструменты. В этой статье пойдёт речь об одном из мощных помощников для поиска багов, в том числе и при работе с Unreal Engine.
У статического анализатора PVS-Studio богатый опыт сотрудничества с Epic Games и Unreal Engine. И с каждым релизом в PVS-Studio появляется всё больше механизмов и специализированных для Unreal Engine диагностических правил. Давайте же посмотрим, к каким результатам привели годы развития интеграции PVS-Studio с одним из самых популярных игровых движков.
Примечание. Подробнее о необходимости статического анализа в GameDev мы рассказывали в статье ранее на примере движка Unity.
Установка PVS-Studio и плагинов
Подключить PVS-Studio к Unreal Engine несложно. Скачиваем инсталлятор по ссылке и следуем инструкции — устанавливаем сам PVS-Studio и плагин для Visual Studio 2022. Понадобится Enterprise-лицензия, если её нет, можно получить триальную по этой ссылке.
Быстрый старт на Windows описан в документации.
Способы запуска анализа
Попытка проанализировать проект на Unreal Engine привычным способом — через плагин в Visual Studio — приведёт к сообщению о невозможности запуска анализа. Unreal Engine использует собственную систему сборки UnrealBuildTool (UBT), и именно через неё должен запускаться анализ. Поэтому давайте рассмотрим первый способ запуска анализа — через флаги UBT.
Флаги UnrealBuildTool
Как я уже ранее упоминал, Unreal Engine компилирует проекты через UBT. Чтобы проанализировать проект, нужно добавить в UBT следующий флаг:
-StaticAnalyzer=PVSStudio
Этот флаг нужно прописать в поле NMake Command Line
в настройках проекта. В этом случае вместо сборки проекта будет производиться анализ. При первом запуске будет произведён полный анализ проекта, при последующих — только изменённых файлов (инкрементальный анализ). Если указать флаг в команде Rebuild
, анализ будет запускаться каждый раз для всего проекта.
Подробности о сценариях запуска сборки и анализа можно найти в документации.
Задание параметров в .target.cs файлах
Если вы часто пересоздаёте .sln
или регулярно пересобираете проект, удобнее всего зашить параметры анализа прямо в .target.cs
.
Для этого просто добавьте одну строку в конструктор Target
, в зависимости от версии Unreal Engine.
Unreal Engine 5.0 и ниже:
public MyProjectTarget(TargetInfo Target) : base(Target)
{
....
WindowsPlatform.StaticAnalyzer = WindowsStaticAnalyzer.PVSStudio;
....
}
Unreal Engine 5.1 и выше:
public MyProjectTarget(TargetInfo Target) : base(Target)
{
....
StaticAnalyzer = StaticAnalyzer.PVSStudio;
....
}
Через файл BuildConfiguration.xml
Если нет возможности менять .target.cs
файлы, то можно задать параметры анализа через отдельный конфигурационный файл — BuildConfiguration.xml
.
Пример минимальной конфигурации:
<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
<BuildConfiguration>
<StaticAnalyzer>
PVSStudio
</StaticAnalyzer>
</BuildConfiguration>
</Configuration>
Исключение автогенерируемых файлов и файлов ядра Unreal Engine из анализа проекта
Файлы *.gen.cpp
генерируются экосистемой Unreal Engine. Их анализ бесполезен и замедляет процесс. Также важно исключить из анализа исходники самого Unreal Engine, но это лучше делать, если вы не модифицируете движок.
Для исключения из анализа автогенерируемых файлов добавьте маску *.gen.cpp
в настройку плагина PathMasks
. Тут важно сказать, что начиная с Unreal Engine 5.4, анализ автогенерируемых файлов по умолчанию отключён, но если вдруг вы решили всё же проанализировать эти файлы, то можете использовать флаг -StaticAnalyzerIncludeGenerated
в UBT.
Исключить из анализа модуль ядра Unreal Engine можно двумя способами:
1. Добавлением в UnrealBuildTool
флага:
-StaticAnalyzerProjectOnly
2. Добавлением в файл target.cs
:
bStaticAnalyzerProjectOnly = true;
Эти настройки очень важны для ускорения процесса анализа вашего проекта. Конечно, есть ещё куча других параметров, и если вам интересно про них узнать, то наливайте чаёк и открывайте эту страницу.
Что нового в анализе проектов на основе Unreal Engine
Новый формат отчёта и навигация
Мы переработали формат вывода предупреждений, выдаваемых при запуске анализа через UnrealBuildTool
. Наш анализатор уже давно генерирует отчёты в новом формате, и его главная фишка — поддержка многофайловой навигации. Раньше, если вы запускали анализ через UnrealBuildTool
, она была недоступна, но сейчас всё работает как надо.
Распределённая сборка и анализ через Horde + UBA
В Unreal Engine 5.5 появилась удобная связка — Horde и UBA (Unreal Build Accelerator). Она умеет распределять сборку (а теперь ещё и анализ) по нескольким машинам в сети, серьёзно ускоряя весь процесс.
Horde — это кластерная система сборки от Epic Games, использующая MongoDB и Redis. Ставится либо через MSI, либо через Docker.
UBA — специальный executor, который можно включить в конфиге, чтобы задачи сборки и анализа шли параллельно на агентах.
Как подключить анализ:
Разворачиваем Horde: на сервере поднимаем MongoDB и Redis, настраиваем Horde, привязываем свою учётную запись Epic Games к GitHub и принимаем инвайт в организацию.
Агенты: ставим HordeAgent на нужные машины, задаём
ServerUrl
,Enroll
и готово.Включаем анализ: в
.target.cs
добавляем:StaticAnalyzer = StaticAnalyzer.PVSStudio;
.Настраиваем конфиг: в
BuildConfiguration.xml
включаемbAllowUBAExecutor
, указываем нужныйServer
иWindowsPool
.
После этого и сборка, и статический анализ будут распределяться по агентам. Это уже действительно быстрая разработка, особенно на крупных проектах. По ссылке вы узнаете все тонкости функционала и настроек, рекомендую ознакомиться.
Оптимизация памяти
При анализе проектов на основе Unreal Engine можно заметить, что PVS-Studio потребляет больше памяти, чем хотелось бы. Есть две основные причины:
Unity build (Single Compilation Unit). Unreal Engine по умолчанию объединяет кучу
.cpp
файлов в один большой. Это позволяет неплохо ускорить сборку, но также требует больше ресурсов для анализа.Шаблоны. Unreal Engine активно использует шаблоны, а для качественного анализа нужно проводить анализ каждого инстанцирования. Это тоже даёт нагрузку.
Мы провели работу над оптимизацией ядра C и C++ анализатора, уменьшив потребление памяти и время анализа. Однако если проект большой, лучше временно отключить Unity build. Как это сделать — рассказано здесь.
Диагностические правила, специфичные для проектов на основе Unreal Engine
Ещё хочется напомнить, что в PVS-Studio доступны диагностические правила, специфичные для проектов на основе Unreal Engine:
V1100: Объявление нестатического поля класса в виде указателя на тип, унаследованный от UObject
, внутри класса/структуры, которые не унаследованы от типа UObject
. Сборщик мусора Unreal Engine может уничтожить объект, адресуемый этим указателем.
V1102: Объявление сущности, несоответствующей соглашениям о наименованиях для проектов на основе Unreal Engine. Соответствие этому соглашению требуется для корректной работы Unreal Header Tool.
Если у вас есть идеи по новым диагностическим правилам, мы будем рады предложениям. Более подробно об этом можно почитать здесь.
Учёт сторонних библиотек
Была занятная история: у проектов на основе Unreal Engine иногда "исчезали" срабатывания диагностических правил, включая даже наши специфичные и описанные ранее. Разобравшись, мы выяснили, что в кодовой базе движка есть файл MicrosoftPlatformCodeAnalysis.h
, в котором прописаны комментарии вида //-V:: (number)
. Они отключают диагностические правила по всей кодовой базе, включая ваш код.
Чтобы решить проблему, мы добавили флаг --analysis-paths mode=path
, который позволяет игнорировать подавления из стороннего кода. У него есть режимы:
1.mode
— это набор из следующих значений:
skip-analysis
— исключает из анализа указанные файлы и директории;skip-settings
— игнорирует чтение настроек из указанных файлов и директорий;skip
— объединяет функционал режимовskip-analysis
иskip-settings
;
2. path
— это файлы и каталоги, к которым будут применяться настройки.
Если вы собираете проект с флагом -StaticAnalyzerProjectOnly
, UnrealBuildTool
сам передаёт анализатору флаг --analysis-paths
с нужными параметрами. Это позволяет запустить анализ только пользовательского проекта, игнорируя модуль ядра Unreal Engine и вместе с этим все нежелательные подавления диагностических правил.
Подробнее про проблему и её устранение можно прочитать тут.
Заключение
PVS-Studio легко интегрируется в существующую сборочную систему. Чем раньше вы включите его в процесс разработки, тем меньше будет сюрпризов на релизе. А бесплатно попробовать проверить свой проект на основе Unreal Engine с помощью PVS-Studio можно по этой ссылке.
Благодарю за внимание!