Когда PVS-Studio объявила, что наконец-то выпустила самостоятельную версию, не требующую для работы Visual Studio, я, конечно, не мог это проигнорировать :) До этого я уже поигрался с пробной версией, используя код одного из старые проекты.
Теперь у нас есть возможность взглянуть на код нашего последнего проекта, который собирается в среде разработки AVR Studio (основанной на eclipse).
Для работы нужны файлы сразу после препроцессора.
Среда AVR Studio может это сделать, за одним небольшим исключением — после включения флага «Только препроцессор» выходные данные фактически содержат файлы после препроцессора — но все равно с расширением .
o вместо ожидаемого .
i. Что ж, 5-минутный Python-скрипт решает это недоразумение, и анализатор прекрасно запускается! На удивление сообщений мало – около двух десятков.
Большинство из них — это незначительные комментарии или ложные срабатывания (во встроенных случаях происходит запись одного и того же значения в регистр дважды подряд, но анализатор видит в этом потенциальную проблему (и я в целом с этим согласен — лучше перестраховаться и проверить такие места)).
В паре мест настоящие опечатки и ошибки копипаста.
Например, переменная типа одного перечисления сравнивается со значением из другого перечисления.
Либо одной и той же переменной присваиваются два разных значения подряд (хотя, как было сказано выше, в большинстве случаев это было ложное срабатывание при последовательной записи в регистр).
Но самое интересное, ради чего я и пишу этот пост, — это одна-единственная строчка «Возможное разыменование NULL-указателя»… Так получилось, что по всему коду такая конструкция типа
И буквально в нескольких функциях дизайн немного отличался:void fun(error_t * perr) { *perr = SUCCESS; .
if (something) { *perr = SOME_ERROR; } }
void init(void)
{
error_t err = SUCCESS;
.
fun(&err);
}
Пока однажды после одного из небольших рефакторингов в одном из мест не появилось следующее:
void some_init(void)
{
error_t *perr = SUCCESS;
.
some_fun(perr);
}
Собственно, анализатор выругался на этой строчке.
УСПЕХ, конечно, имел значение 0. Давайте отмотаем время немного назад, к тому моменту, когда это изменение попало в репозиторий.
После рефакторинга очень большой набор автоматических тестов продолжал успешно выполняться.
Проверка кода оставила эту строку незамеченной (слишком часто в коде появлялись строки *perr = SUCCESS).
Примерно через 30 дней после того самого коммита ночные тесты впервые провалились.
Воспроизвести падение не удалось.
Затем испытания снова провалились.
И далее.
Экспериментально было установлено, что сбой происходит в среднем один раз на каждые тридцать запусков набора тестов.
На поиск ошибки команда потратила около 50 часов.
Безуспешно.
Правда, нам удалось локализовать коммит, после которого все началось — но причину так и не нашли.
Причина, кстати, была на две ступени ниже.
Функция some_fun(perr) внутренне называется some_other_fun(perr), и эта функция называется some_ Third_fun(perr).
И уже в some_ Third_fun(perr) был код, проверявший, произошла ли ошибка: for(number_of_loops)
{
some_action(perr);
if (*perr != SUCCESS)
return;
}
Те.
несмотря на то, что в функции some_action ошибок не возникло (что было очень нетривиально, с участием кучи внешней периферии - именно поэтому локализация проблемы оказалась не самой простой задачей), продолжение цикла зависело от записанного в нее значения адрес 0 (в большинстве случаев встроенный нулевой адрес совершенно законен).
И в подавляющем большинстве случаев на этот адрес записывалось 0. Резюме: ошибка, на поиск которой безуспешно ушло около 50 часов, была обнаружена и исправлена менее чем за час с помощью одного запуска анализатора! Веская причина использовать анализатор? Увы, не всегда.
В частности, у нас точно такой же случай: проект с оплатой по временной и материальной схеме.
Поскольку 50 часов, потраченные на поиск, оплачиваются заказчиком, для руководства внедрение анализатора означает прямые потери:((( И кстати: в проекте используется FreeRTOS. Итак, в ее коде не было ни одного предупреждения! И да, этот пост чисто из любви к искусству анализаторов.
Теги: #статический анализ кода #pvs-studio #C++ #программирование #Идеальный код #C++
-
15 Интересных И Полезных Сервисов От Google
19 Oct, 24 -
Привычка, Хабрахабр И Твиттер
19 Oct, 24