Хабрахабр

В очередной раз анализатор PVS-Studio оказался внимательнее человека

Возьми баг

Изучая предупреждения анализатора PVS-Studio в процессе проверки различных открытых проектов, мы вновь и вновь убеждаемся, сколь полезен может быть этот инструмент. Анализатор кода невероятно внимателен и никогда не устаёт. Он указывает на ошибки, которые ускользают даже при внимательном обзоре кода. Рассмотрим очередной такой случай.
В предыдущий раз я написал аналогичную заметку, изучая исходный код проекта StarEngine: 2D Game Engine. Теперь анализатор показал своё превосходство надо мной в ходе проверки фреймворка Qt.

Прошло много времени, проект изменился, а в анализаторе PVS-Studio появилось много новых диагностик. Последний раз мы проверяли фреймворк Qt в 2014 году. Значит, вполне можно написать очередную статью, чем я и занялся.

Выписывая интересные примеры ошибок, я повстречал вот такой код:

QWindowsCursor::CursorState QWindowsCursor::cursorState()
; CURSORINFO cursorInfo; cursorInfo.cbSize = sizeof(CURSORINFO); if (GetCursorInfo(&cursorInfo)) { if (cursorInfo.flags & CursorShowing) // <= V616 ....
}

Для этого кода PVS-Studio выдал предупреждение:

qwindowscursor.cpp 669 V616 CWE-480 The 'CursorShowing' named constant with the value of 0 is used in the bitwise operation.

«Эх, что-то мы сломали в механизмах обработки неименованных перечислений», — вздохнул я, и выписал этот случай в багтрекер как ошибку, приводящую к ложному срабатыванию. Для проверки использовалась нестабильная версия PVS-Studio, поэтому моя вера в анализатор дрогнула.

Ведь всего несколькими строчками выше написано, что константа CursorShowing равна 1. Я был абсолютно уверен, что ошибается именно анализатор.

Я несколько раз просмотрел код, чтобы убедиться, что анализатор неправ. При этом я старался быть внимательным! Я оформил этот фрагмент кода и соответствующее сообщение как ошибку в багтрекере.

Прав именно анализатор, а не человек. Я провёл внимательный обзор этого маленького участка кода и всё равно облажался.

Разница только в первой букве! При подробном изучении ситуации выяснилось, что выше объявляется именованная константа cursorShowing, а в условии используется константа CursorShowing. В одном месте она строчная, а в другом прописная.

Потому, что константа CursorShowing тоже существует. Почему код компилируется? Вот её объявление:

class QWindowsCursor : public QPlatformCursor
{
public: enum CursorState { CursorShowing, CursorHidden, CursorSuppressed }; ....
}

Как видите, константа CursorShowing равна 0. Поэтому анализатор PVS-Studio абсолютно прав, сообщая, что условие (cursorInfo.flags & CursorShowing) не имеет смысла. Условие является всегда ложным.

Любите статический анализ кода! Анализатор нашёл замечательную опечатку. 🙂

Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Andrey Karpov. Once again the PVS-Studio analyzer has proved to be more attentive than a person.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»