﻿# Статический анализ защищает ваш код от бомб замедленного действия

Статический анализ кода позволяет выявлять и устранять многие дефекты на раннем этапе\. Более того, можно обнаружить спящие ошибки, которые в момент появления никак не проявляют себя\. Они могут доставить массу проблем в будущем, потребовав для своего обнаружения многих часов отладки\. Рассмотрим пример такой спящей ошибки\.

![0848_Timebomb_ru/image1.png](https://import.viva64.com/docx/blog/0848_Timebomb_ru/image1.png)

Чтобы показать преимущество регулярного использования статического анализатора PVS\-Studio, мы настроили у себя регулярную проверку проекта [Blender](https://github.com/blender/blender)\. Подробнее про эту идею мой коллега писал [здесь](https://pvs-studio.ru/ru/blog/posts/cpp/0799/)\.

Я временами посматриваю на предупреждения, сгенерированные для нового или изменённого кода Blender\. Новые ошибки находятся регулярно, но большинство из них скучные или несущественные\. Я, как рыбак, сижу и жду, когда будет что\-то интересное, про что захочется написать\. Сегодня как раз такой случай\.

```cpp
void UI_but_drag_set_asset(uiBut *but,
                           const AssetHandle *asset,
                           const char *path,
                           int import_type,
                           int icon,
                           struct ImBuf *imb,
                           float scale)
{
  ....
  asset_drag->asset_handle = MEM_mallocN(sizeof(asset_drag->asset_handle),
                                         "wmDragAsset asset handle");
  *asset_drag->asset_handle = *asset;
  ....
}
```

Код должен выделить буфер в памяти, достаточный для хранения структуры типа _AssetHandle_\. Такова была задумка программиста\. Но на самом деле он выделяет буфер, равный не размеру структуры, а размеру указателя\.

Ошибка здесь:

```cpp
sizeof(asset_drag->asset_handle)
```

Правильный вариант:

```cpp
sizeof(*asset_drag->asset_handle)
```

Анализатор выявил эту ошибку, выдав предупреждение: [V568](https://pvs-studio.ru/ru/docs/warnings/v568/): It's odd that 'sizeof\(\)' operator evaluates the size of a pointer to a class, but not the size of the 'asset\_drag\-\>asset\_handle' class object\. interface\.c 6192

Всё просто\. Классический паттерн ошибки, с которым мы [встречались](https://pvs-studio.ru/ru/blog/examples/v568/) в различных проектах\. Интересно другое\! Этот код сейчас работает правильно\! Автору кода повезло\. Посмотрим, что собой представляет структура _AssetHandle_:

```cpp
typedef struct AssetHandle {
  const struct FileDirEntry *file_data;
} AssetHandle;
```

Структура сейчас содержит в себе ровно один указатель\. Получается, что размер структуры совпадает с размером указателя\!

Перед нами красивая бомба замедленного действия\. Этот код будет надёжно и стабильно работать годами\. Он будет полностью работоспособен до тех пор, пока кто\-то не захочет добавить в структуру новое поле\.

В этот момент приложение сломается\. Причём будет непонятно, что и где именно сломалось\. Под структуру будет выделяться памяти меньше, чем требуется\. Хорошо если программисту повезёт и при выходе за границу буфера возникнет [Access Violation](https://pvs-studio.ru/ru/blog/terms/0063/)\. Но, скорее всего, просто будет портиться какая\-то память, и разработчика могут ждать часы мучительной отладки кода\.

Используйте статический анализ кода, чтобы существенно улучшить качество и надёжность кода\. Это полезно как в краткосрочной, так и в долгосрочной перспективе\.

Статический анализ способен выявить не все ошибки\. Однако преимуществ от его регулярного использования больше, чем затрат на ежедневный просмотр отчёта с новыми предупреждениями\. Недавно в статье наш пользователь как раз описывал, как он пришёл к выводу, что лучше запускать анализатор, чем [три дня отлаживаться](https://pvs-studio.ru/ru/blog/posts/cpp/0847/)\.