26
Как мы уменьшили количество ошибок в Unreal Engine с помощью статического анализа кода Евгений Рыжков [email protected] ООО «СиПроВер» www.viva64.com 1/26

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

Embed Size (px)

Citation preview

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

Как мы уменьшили количество ошибок в Unreal Engine

с помощью статического анализа кода

Евгений Рыжков

[email protected]

ООО «СиПроВер»

www.viva64.com

1/26

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

Структура доклада

• Этапы внедрения анализатора кода в живой проект.

• Примеры ошибок из кода Unreal Engine.

• Типы исправлений в коде.

• Зачем вообще знакомиться со статическим анализом.

2/26

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

Этапы внедрения статического анализатора кода

3/26

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

Этап 0. Научить инструмент проверять проект• Убедиться, что весь код компилируется

• Убедиться, что весь код корректно проверяется анализатором

4/26

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

Пример ошибки из кода 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

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

Этап 1. Борьба с имеющимися сообщениями• Запустили анализатор на существующем проекте – получили 2000

сообщений.

• Бросаться их сразу править – плохая идея. Менеджер проекта негодует.

• Оставить как есть – не увидите новых сообщений.

• Обязательно в инструменте должна быть возможность скрыть этим сообщения. Где-то нет такой возможности? Не тот инструмент.

6/26

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

Пример ошибки из кода 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

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

Этап 2. Настройка регулярного запуска на билд-сервере (и на машинах разработчиков)

• Абсолютно необходимая вещь – это настройка запуска на билд-сервере.

• Надо давать всем разработчикам возможность ознакомиться с результатами проверки.

• В идеале регулярный запуск нужен не только на билд-сервере по ночам, но и на машинах разработчиков во время работы.

8/26

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

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 verifiedagainst nullptr. Check lines: 1844, 1846. animsequence.cpp 1844

9/26

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

Этап 3. Правим новые ошибки

• Убедить разработчиков править все новые ошибки, чтобы было 0 сообщений.

• Здесь инструменты статического анализа могут предложить только плетку менеджеру проекта, к сожалению.

10/26

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

Пример ошибки из кода 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

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

Этап 4. Правим старые ошибки

• Очень желательно все-таки победить старые ошибки.

• Поговорим про скорость правки ошибок.

12/26

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

Ожидаемая скорость правки ошибок

• Количество ошибок уменьшается равномерно с каждым рабочим днём.

13/26

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

Фактическая скорость правки ошибок

• На самом деле, сообщения исчезают в начале быстрее, чем потом.

14/26

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

На что ушли 17 рабочих дней в UE?Количество предупреждений анализатора в различные дни

Сначала правятся легкие ошибки, потом посложнее и самые сложные в конце

15/26

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

На что ушли 17 рабочих дней в UE:расшифровка• С нашей стороны работало 2 программиста.

• Код UE нам совершенно не знаком.

• Коммуникации с программистами заказчика затруднены

(Hello, USA TimeZone).

16/26

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

Старые ошибки поправлены! Можно расслабиться?

17/26

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

Пример ошибки из кода Unreal Engine

V561 It's probably better to assign value to 'Existing' variable than to declare it anew. Previousdeclaration: 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

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

Типы найденных ошибок (не код)

• Настоящие ошибки.

• «Запахи».

• Правки, чтобы «угодить» анализатору кода.

19/26

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

«Пахнущий код»: ошибки нет, но анализатор прав

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

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

Примеры ошибок, которые появились "на наших глазах"

21/26

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

Пример ошибки из кода 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

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

Пример ошибки из кода 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

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

Выводы по результатам проверки Unreal Engine• Код проекта Unreal Engine весьма качественный.

• Править чужой незнакомый код часто очень сложно. Свой –намного легче.

• Скорость "переработки" предупреждений не линейна.

• Максимальная польза от статического анализа может быть получена только при его регулярном использовании.

24/26

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

Пара слов о программистской культурев России и мире, или «Зачем вообще знакомиться со статическим анализом?»

• Люди на западе применяют эту практику давно и успешно.

• Знание принципов и инструментов статического анализа кода дает +10 на собеседовании разработчика и +20 при внедрении в своем проекте. И должность Team Leader в придачу.

25/26

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

Q&A

• Написать письмо: [email protected]

• Подписаться на твиттер: https://twitter.com/Code_Analysis

• Зайти на сайт: www.viva64.com

• Подойти на конференции и спросить что-то (в большинстве случаем мы не кусаемся).

26/26