SlideShare a Scribd company logo
Как мы уменьшили количество ошибок
в Unreal Engine
с помощью статического анализа кода
Евгений Рыжков
evg@viva64.com
ООО «СиПроВер»
www.viva64.com
1/26
Структура доклада
• Этапы внедрения анализатора
кода в живой проект.
• Примеры ошибок из кода
Unreal Engine.
• Типы исправлений в коде.
• Зачем вообще знакомиться со
статическим анализом.
2/26
Этапы внедрения статического
анализатора кода
3/26
Этап 0. Научить инструмент проверять
проект
• Убедиться, что весь код компилируется
• Убедиться, что весь код корректно проверяется анализатором
4/26
Пример ошибки из кода Unreal Engine
if (*Buffer == TCHAR('"')) {
while (*Buffer &&
*Buffer != TCHAR('"') &&
*Buffer != TCHAR('n') &&
*Buffer != TCHAR('r'))
{
Buffer++;
}
V637 Two opposite conditions were encountered. The second condition is always false.
Check lines: 310, 312. propertystruct.cpp 310
5/26
Этап 1. Борьба с имеющимися
сообщениями
• Запустили анализатор на существующем проекте – получили 2000
сообщений.
• Бросаться их сразу править – плохая идея. Менеджер проекта
негодует.
• Оставить как есть – не увидите новых сообщений.
• Обязательно в инструменте должна быть возможность скрыть
этим сообщения. Где-то нет такой возможности? Не тот
инструмент.
6/26
Пример ошибки из кода Unreal Engine
V612 An unconditional 'return' within a loop.
unrealaudiotestgenerators.cpp 49
static float WrapTwoPi(float Value)
{
while (Value >= TWO_PI)
{
return Value -= TWO_PI;
}
while (Value < 0)
{
return Value += TWO_PI;
}
return Value;
} 7/26
Этап 2. Настройка регулярного запуска на билд-
сервере (и на машинах разработчиков)
• Абсолютно необходимая вещь – это настройка запуска на билд-
сервере.
• Надо давать всем разработчикам возможность ознакомиться с
результатами проверки.
• В идеале регулярный запуск нужен не только на билд-сервере по
ночам, но и на машинах разработчиков во время работы.
8/26
void FillUpTransformBasedOnRig(....)
{
....
const URig* Rig = Skeleton->GetRig();
int32 NodeNum = Rig->GetNodeNum();
if (Rig && NodeNum > 0)
{
....
}
....
}
Пример ошибки из кода Unreal Engine
V595 The 'Rig' pointer was utilized before it was verified
against nullptr. Check lines: 1844, 1846.
animsequence.cpp 1844
9/26
Этап 3. Правим новые ошибки
• Убедить разработчиков править все новые ошибки, чтобы было 0
сообщений.
• Здесь инструменты статического анализа могут предложить
только плетку менеджеру проекта, к сожалению.
10/26
Пример ошибки из кода Unreal Engine
V579 The Memcmp function receives the pointer and its size as arguments. It is possibly a
mistake. Inspect the third argument. pimplrecastnavmesh.cpp 172
bool FRecastQueryFilter::IsEqual(
const INavigationQueryFilterInterface* Other) const
{
return FMemory::Memcmp(this, Other, sizeof(this)) == 0;
}
11/26
Этап 4. Правим старые ошибки
• Очень желательно все-таки победить старые ошибки.
• Поговорим про скорость правки ошибок.
12/26
Ожидаемая скорость
правки ошибок
• Количество ошибок
уменьшается
равномерно с каждым
рабочим днём.
13/26
Фактическая скорость
правки ошибок
• На самом деле,
сообщения исчезают в
начале быстрее, чем
потом.
14/26
На что ушли 17 рабочих дней в UE?
Количество предупреждений
анализатора в различные дни
Сначала правятся легкие ошибки, потом
посложнее и самые сложные в конце
15/26
На что ушли 17 рабочих дней в UE:
расшифровка
• С нашей стороны работало 2 программиста.
• Код UE нам совершенно не знаком.
• Коммуникации с программистами заказчика затруднены
(Hello, USA TimeZone).
16/26
Старые ошибки поправлены!
Можно расслабиться?
17/26
Пример ошибки из кода Unreal Engine
V561 It's probably better to assign value to 'Existing' variable than to declare it anew. Previous
declaration: streamablemanager.cpp, line 325. streamablemanager.cpp 332
FStreamable* Existing = StreamableItems.FindRef(TargetName);
....
if (!Existing)
{
TargetName = ResolveRedirects(TargetName);
FStreamable* Existing = StreamableItems.FindRef(TargetName);
}
if (Existing && Existing->bAsyncLoadRequestOutstanding)
....
18/26
Типы найденных ошибок (не код)
• Настоящие ошибки.
• «Запахи».
• Правки, чтобы «угодить» анализатору кода.
19/26
«Пахнущий код»: ошибки нет, но
анализатор прав
if (InitializationState == Working)
{
//bool AllSuccessful = true;
//Insert other dependencies here
if (InitializationState == Working
/* && AllSuccessful */)
{
InitializationState = Success;
}
}
V571 Recurring check. This condition was already verified in line 357. questionblock.cpp 363
20/26
Примеры ошибок, которые
появились "на наших глазах"
21/26
Пример ошибки из кода Unreal Engine
virtual FString ToString() const override
{
if (Token.TokenType == FBasicToken::TOKEN_Identifier ||
FBasicToken::TOKEN_Guid)
{
....
}
V560 A part of conditional expression is always true: FBasicToken::TOKEN_Guid.
k2node_mathexpression.cpp 235
22/26
Пример ошибки из кода Unreal Engine
static void GetArrayOfSpeakers(....)
{
Speakers.Reset();
uint32 ChanCount = 0;
for (uint32 SpeakerTypeIndex = 0;
SpeakerTypeIndex < ESpeaker::SPEAKER_TYPE_COUNT,
ChanCount < NumChannels; ++SpeakerTypeIndex)
....
}
V521 Such expressions using the ',' operator are dangerous. Make sure the expression is
correct. unrealaudiodevicewasapi.cpp 128
,
23/26
Выводы по результатам проверки
Unreal Engine
• Код проекта Unreal Engine весьма качественный.
• Править чужой незнакомый код часто очень сложно. Свой –
намного легче.
• Скорость "переработки" предупреждений не линейна.
• Максимальная польза от статического анализа может быть
получена только при его регулярном использовании.
24/26
Пара слов о программистской культуре
в России и мире, или «Зачем вообще
знакомиться со статическим анализом?»
• Люди на западе применяют эту практику давно и успешно.
• Знание принципов и инструментов статического анализа кода
дает +10 на собеседовании разработчика и +20 при внедрении в
своем проекте. И должность Team Leader в придачу.
25/26
Q&A
• Написать письмо: evg@viva64.com
• Подписаться на твиттер: https://twitter.com/Code_Analysis
• Зайти на сайт: www.viva64.com
• Подойти на конференции и спросить что-то (в большинстве
случаем мы не кусаемся).
26/26

More Related Content

PDF
C++ exceptions
PPTX
Аскетичная разработка браузера
PDF
DI в C++ тонкости и нюансы
PPT
Юнит-тестирование и Google Mock. Влад Лосев, Google
PDF
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
PPTX
Григорий Демченко, Асинхронность и неблокирующая синхронизация
PPTX
Павел Беликов, Как избежать ошибок, используя современный C++
PDF
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
C++ exceptions
Аскетичная разработка браузера
DI в C++ тонкости и нюансы
Юнит-тестирование и Google Mock. Влад Лосев, Google
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Павел Беликов, Как избежать ошибок, используя современный C++
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM

What's hot (20)

PDF
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
PDF
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
PDF
Для чего мы делали свой акторный фреймворк и что из этого вышло?
PDF
Parallel STL
ODP
Как за час сделать недельную работу
PPTX
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
PPTX
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
PDF
Пояснения к статье про Copy-Paste
PDF
Антон Полухин, Немного о Boost
PDF
Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...
PDF
Как перестать отлаживать асинхронный код и начать жить / Андрей Саломатин (Pr...
PDF
Павел Довгалюк, Обратная отладка
PDF
Использование юнит-тестов для повышения качества разработки
PPTX
Когда в C# не хватает C++
PPTX
Когда в C# не хватает C++ . Часть 2.
PPTX
Когда в C# не хватает C++ . Часть 3.
PPTX
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
PPTX
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
PPTX
Основы и применение статического анализа кода при разработке лекция 1
PPTX
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Parallel STL
Как за час сделать недельную работу
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Пояснения к статье про Copy-Paste
Антон Полухин, Немного о Boost
Сравнение статического анализа общего назначения из Visual Studio 2010 и PVS-...
Как перестать отлаживать асинхронный код и начать жить / Андрей Саломатин (Pr...
Павел Довгалюк, Обратная отладка
Использование юнит-тестов для повышения качества разработки
Когда в C# не хватает C++
Когда в C# не хватает C++ . Часть 2.
Когда в C# не хватает C++ . Часть 3.
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Основы и применение статического анализа кода при разработке лекция 1
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Ad

Viewers also liked (20)

PDF
QML\Qt Quick на практике
PDF
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
PPT
Евгений Крутько, Многопоточные вычисления, современный подход.
PPTX
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
PDF
Визуализация автомобильных маршрутов
PDF
Функциональный микроскоп: линзы в C++
PDF
HPX: C++11 runtime система для параллельных и распределённых вычислений
PPTX
Ranges calendar-novosibirsk-2015-08
PDF
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
PDF
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
PDF
Антон Бикинеев, Reflection in C++Next
PPTX
Григорий Демченко, Универсальный адаптер
PDF
Clang tidy
PPTX
Алексей Кутумов, C++ без исключений, часть 3
PDF
Догнать и перегнать boost::lexical_cast
PPTX
Фитнес для вашего кода: как держать его в форме
PPTX
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
PPTX
C++ Core Guidelines
PPTX
Quality assurance of large c++ projects
PDF
Fuzzing: The New Unit Testing
QML\Qt Quick на практике
Дмитрий Кашицын, Вывод типов в динамических и не очень языках II
Евгений Крутько, Многопоточные вычисления, современный подход.
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Визуализация автомобильных маршрутов
Функциональный микроскоп: линзы в C++
HPX: C++11 runtime система для параллельных и распределённых вычислений
Ranges calendar-novosibirsk-2015-08
Тененёв Анатолий, Boost.Asio в алгоритмической торговле
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Антон Бикинеев, Reflection in C++Next
Григорий Демченко, Универсальный адаптер
Clang tidy
Алексей Кутумов, C++ без исключений, часть 3
Догнать и перегнать boost::lexical_cast
Фитнес для вашего кода: как держать его в форме
Evgeniy Muralev, Mark Vince, Working with the compiler, not against it
C++ Core Guidelines
Quality assurance of large c++ projects
Fuzzing: The New Unit Testing
Ad

Similar to Как мы уменьшили количество ошибок в Unreal Engine с помощью статического анализа кода (20)

PPTX
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
PPTX
Статический анализ кода проектов, построенных на движке Unreal Engine
PPTX
Static code analysis of the projects built on Unreal Engine
PPTX
Статический анализ и написание качественного кода на C/C++ для встраиваемых с...
PPTX
Что могут статические анализаторы, чего не могут программисты и тестировщики
PDF
Статический анализ исходного кода на примере WinMerge
PPTX
Как команда PVS-Studio может улучшить код операционной системы Tizen
PPTX
Статический анализ кода
PPTX
статический анализ кода
PPTX
Качество кода игровых движков: неужели всё так плохо?
PPTX
SAST и Application Security: как бороться с уязвимостями в коде
PDF
Цена ошибки
PPTX
Цена ошибки
PDF
Intel IPP Samples for Windows - работа над ошибками
PPTX
Как создать качественный статический анализатор
PPTX
Улучшение качества открытого программного обеспечения с помощью инструментов ...
PPTX
Статические анализаторы кода как DevSecOps решение
PPTX
Статический анализ: ищем ошибки... и уязвимости?
PDF
Разница в подходах анализа кода компилятором и выделенным инструментом
PPTX
PVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio. Статический анализатор кода. Windows/Linux, C/C++/C#
Статический анализ кода проектов, построенных на движке Unreal Engine
Static code analysis of the projects built on Unreal Engine
Статический анализ и написание качественного кода на C/C++ для встраиваемых с...
Что могут статические анализаторы, чего не могут программисты и тестировщики
Статический анализ исходного кода на примере WinMerge
Как команда PVS-Studio может улучшить код операционной системы Tizen
Статический анализ кода
статический анализ кода
Качество кода игровых движков: неужели всё так плохо?
SAST и Application Security: как бороться с уязвимостями в коде
Цена ошибки
Цена ошибки
Intel IPP Samples for Windows - работа над ошибками
Как создать качественный статический анализатор
Улучшение качества открытого программного обеспечения с помощью инструментов ...
Статические анализаторы кода как DevSecOps решение
Статический анализ: ищем ошибки... и уязвимости?
Разница в подходах анализа кода компилятором и выделенным инструментом
PVS-Studio, решение для разработки современных ресурсоемких приложений

More from Platonov Sergey (14)

PPTX
Евгений Зуев, С++ в России: Стандарт языка и его реализация
PDF
Использование maven для сборки больших модульных c++ проектов на примере Odin...
PDF
One definition rule - что это такое, и как с этим жить
PDF
Concepts lite
PDF
Денис Кормалев Метаобъектная система Qt
PDF
Максим Хижинский Lock-free maps
PPT
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
PDF
High quality library from scratch
PDF
С++ without new and delete
PDF
Categories for the Working C++ Programmer
PDF
Библиотека Boost с нуля на примере Boost.DLL
PPTX
Оптимизация трассирования с использованием Expression templates
PDF
Практика Lock-free. RealTime-сервер
PPTX
С++ without new and delete
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Использование maven для сборки больших модульных c++ проектов на примере Odin...
One definition rule - что это такое, и как с этим жить
Concepts lite
Денис Кормалев Метаобъектная система Qt
Максим Хижинский Lock-free maps
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
High quality library from scratch
С++ without new and delete
Categories for the Working C++ Programmer
Библиотека Boost с нуля на примере Boost.DLL
Оптимизация трассирования с использованием Expression templates
Практика Lock-free. RealTime-сервер
С++ without new and delete

Как мы уменьшили количество ошибок в Unreal Engine с помощью статического анализа кода

  • 1. Как мы уменьшили количество ошибок в Unreal Engine с помощью статического анализа кода Евгений Рыжков [email protected] ООО «СиПроВер» www.viva64.com 1/26
  • 2. Структура доклада • Этапы внедрения анализатора кода в живой проект. • Примеры ошибок из кода Unreal Engine. • Типы исправлений в коде. • Зачем вообще знакомиться со статическим анализом. 2/26
  • 4. Этап 0. Научить инструмент проверять проект • Убедиться, что весь код компилируется • Убедиться, что весь код корректно проверяется анализатором 4/26
  • 5. Пример ошибки из кода Unreal Engine if (*Buffer == TCHAR('"')) { while (*Buffer && *Buffer != TCHAR('"') && *Buffer != TCHAR('n') && *Buffer != TCHAR('r')) { Buffer++; } V637 Two opposite conditions were encountered. The second condition is always false. Check lines: 310, 312. propertystruct.cpp 310 5/26
  • 6. Этап 1. Борьба с имеющимися сообщениями • Запустили анализатор на существующем проекте – получили 2000 сообщений. • Бросаться их сразу править – плохая идея. Менеджер проекта негодует. • Оставить как есть – не увидите новых сообщений. • Обязательно в инструменте должна быть возможность скрыть этим сообщения. Где-то нет такой возможности? Не тот инструмент. 6/26
  • 7. Пример ошибки из кода Unreal Engine V612 An unconditional 'return' within a loop. unrealaudiotestgenerators.cpp 49 static float WrapTwoPi(float Value) { while (Value >= TWO_PI) { return Value -= TWO_PI; } while (Value < 0) { return Value += TWO_PI; } return Value; } 7/26
  • 8. Этап 2. Настройка регулярного запуска на билд- сервере (и на машинах разработчиков) • Абсолютно необходимая вещь – это настройка запуска на билд- сервере. • Надо давать всем разработчикам возможность ознакомиться с результатами проверки. • В идеале регулярный запуск нужен не только на билд-сервере по ночам, но и на машинах разработчиков во время работы. 8/26
  • 9. void FillUpTransformBasedOnRig(....) { .... const URig* Rig = Skeleton->GetRig(); int32 NodeNum = Rig->GetNodeNum(); if (Rig && NodeNum > 0) { .... } .... } Пример ошибки из кода Unreal Engine V595 The 'Rig' pointer was utilized before it was verified against nullptr. Check lines: 1844, 1846. animsequence.cpp 1844 9/26
  • 10. Этап 3. Правим новые ошибки • Убедить разработчиков править все новые ошибки, чтобы было 0 сообщений. • Здесь инструменты статического анализа могут предложить только плетку менеджеру проекта, к сожалению. 10/26
  • 11. Пример ошибки из кода Unreal Engine V579 The Memcmp function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument. pimplrecastnavmesh.cpp 172 bool FRecastQueryFilter::IsEqual( const INavigationQueryFilterInterface* Other) const { return FMemory::Memcmp(this, Other, sizeof(this)) == 0; } 11/26
  • 12. Этап 4. Правим старые ошибки • Очень желательно все-таки победить старые ошибки. • Поговорим про скорость правки ошибок. 12/26
  • 13. Ожидаемая скорость правки ошибок • Количество ошибок уменьшается равномерно с каждым рабочим днём. 13/26
  • 14. Фактическая скорость правки ошибок • На самом деле, сообщения исчезают в начале быстрее, чем потом. 14/26
  • 15. На что ушли 17 рабочих дней в UE? Количество предупреждений анализатора в различные дни Сначала правятся легкие ошибки, потом посложнее и самые сложные в конце 15/26
  • 16. На что ушли 17 рабочих дней в UE: расшифровка • С нашей стороны работало 2 программиста. • Код UE нам совершенно не знаком. • Коммуникации с программистами заказчика затруднены (Hello, USA TimeZone). 16/26
  • 18. Пример ошибки из кода Unreal Engine V561 It's probably better to assign value to 'Existing' variable than to declare it anew. Previous declaration: streamablemanager.cpp, line 325. streamablemanager.cpp 332 FStreamable* Existing = StreamableItems.FindRef(TargetName); .... if (!Existing) { TargetName = ResolveRedirects(TargetName); FStreamable* Existing = StreamableItems.FindRef(TargetName); } if (Existing && Existing->bAsyncLoadRequestOutstanding) .... 18/26
  • 19. Типы найденных ошибок (не код) • Настоящие ошибки. • «Запахи». • Правки, чтобы «угодить» анализатору кода. 19/26
  • 20. «Пахнущий код»: ошибки нет, но анализатор прав if (InitializationState == Working) { //bool AllSuccessful = true; //Insert other dependencies here if (InitializationState == Working /* && AllSuccessful */) { InitializationState = Success; } } V571 Recurring check. This condition was already verified in line 357. questionblock.cpp 363 20/26
  • 22. Пример ошибки из кода Unreal Engine virtual FString ToString() const override { if (Token.TokenType == FBasicToken::TOKEN_Identifier || FBasicToken::TOKEN_Guid) { .... } V560 A part of conditional expression is always true: FBasicToken::TOKEN_Guid. k2node_mathexpression.cpp 235 22/26
  • 23. Пример ошибки из кода Unreal Engine static void GetArrayOfSpeakers(....) { Speakers.Reset(); uint32 ChanCount = 0; for (uint32 SpeakerTypeIndex = 0; SpeakerTypeIndex < ESpeaker::SPEAKER_TYPE_COUNT, ChanCount < NumChannels; ++SpeakerTypeIndex) .... } V521 Such expressions using the ',' operator are dangerous. Make sure the expression is correct. unrealaudiodevicewasapi.cpp 128 , 23/26
  • 24. Выводы по результатам проверки Unreal Engine • Код проекта Unreal Engine весьма качественный. • Править чужой незнакомый код часто очень сложно. Свой – намного легче. • Скорость "переработки" предупреждений не линейна. • Максимальная польза от статического анализа может быть получена только при его регулярном использовании. 24/26
  • 25. Пара слов о программистской культуре в России и мире, или «Зачем вообще знакомиться со статическим анализом?» • Люди на западе применяют эту практику давно и успешно. • Знание принципов и инструментов статического анализа кода дает +10 на собеседовании разработчика и +20 при внедрении в своем проекте. И должность Team Leader в придачу. 25/26
  • 26. Q&A • Написать письмо: [email protected] • Подписаться на твиттер: https://twitter.com/Code_Analysis • Зайти на сайт: www.viva64.com • Подойти на конференции и спросить что-то (в большинстве случаем мы не кусаемся). 26/26