Информационные технологииStfw.Ru 🔍

Статический анализ кода C++

Для меня красота C++ заключается, в первую очередь, во вседозволенности и ужасающей мощи языка.
🕛 16.11.2009, 16:15
Мы можем работать с памятью так же плотно, как и в C, и в то же время имеем такие средства абстракции, как шаблоны и STL, где параметризовать можно что угодно и чем угодно.
Плата за это соответствующая - не всегда вразумительные ошибки компилятора (попробуйте забыть поставить точку с запятой после определения класса), очень большой срок подготовки и обучения программистов, но самое главное - некоторые баги становятся заметными только во время исполнения программы.
Мы хотим больше полезных ворнингов до запуска наших программ. Одно из средств получения желаемого - статический анализ кода. Статический - значит, не запуская программу. Интересны не только вероятные ошибки, случаи undefined behaviour, утечки памяти, но и вещи вроде недоступности/неиспользуемости кода, рекомендации по повышению интуитивности стиля программирования.

Средства получения метрик ПО, добываемых методами статического анализа в этой статье не рассматриваются. Замечания, связанные со стандартами программирования (фигурная скобочка должна находиться на отдельной строчке, ууууу!!) тоже не интересны.
Критерии оценки простые - количество и полезность находимых багов, простота использования (в частности, отсутствие требований модификации кода), бесплатность/разумная цена/хороший кряк.
Проводим первичный обзор и выдаем на-гора пачку ссылок:
* Static_code_analysis * Wikipedia * Статья Скотта Мейерса об анализаторах * тема на Stack overflow о бесплатных анализаторах

Найденные штуки

Педантичные ключи gcc

В первую очередь, надо использовать все возможные штатные средства. gcc предоставляет следующие интересные ключи, связанные с повышением бдительности компилятора и препроцессора.
* -Wall включает все ворнинги, среди которых совместимость с новым стандартом, границы массива (по-моему, не пашет, хотя говорят, что будет работать с -O2), volatile/register переменные (сообщит, что ему пофигу на твои умные слова и что //register//, а что нет, он будет решать сам), точки следования (i++ + ++i) * -Wextra - еще пачка ворнингов типа пустых тел в if'ах, сравнение signed и unsigned * -pedantic - следование ISO C++ стандарту. Например, запрет типа long long. * -Weffc++ must have опция. Не включается с помощью -Wextra или -Wall и содержит проверку рекомендаций Скотта Мейерса: * o Item 11: Define a copy constructor and an assignment operator for classes with dynamically allocated memory. o Item 12: Prefer initialization to assignment in constructors. o Item 14: Make destructors virtual in base classes. o Item 15: Have «operator=» return a reference to *this. o Item 23: Don't try to return a reference when you must return an object. o Item 6: Distinguish between prefix and postfix forms of increment and decrement operators. o Item 7: Never overload "&&", "||", or ",". * -Woverloaded-virtual - перегрузка виртуальных фунций выглядит плохо. * -Wctor-dtor-privacy - неиспользуемые классы - с приватным конструкторами и деструктором * -Wnon-virtual-dtor - невиртуальный деструктор * -Wold-style-cast - приведение в стиле C - это плохо * -Werr='тип ворнинга' - воспринимать ворнинг как еррор. Для настроящих самураев -Werr без параметров * -Wconversion -Wsign-conversion - ворнинг о преобразовании типа. при котором значение может измениться. Как ни странно, не входит в -Wall * -Winit-self - int i = i; * -Wunreachable-code - код, который никогда не будет выполнен


Разумеется, не сам такой умный, а прочитал всё вот в этой ман-статье про ключи, связанные с предупреждениями
Cppcheck

Пожалуй, самая достойная из найденных программ.
Официальный сайт программы и её плагин для эклипсоидов. Распознает довольно много, находит следующие ошибки:
* некоторые memory leaks, например, отсутствие delete и delete[], отсутствие delete в деструкторе * выход за границу массива * exception'ы, бросаемые в деструкторе * разыменование нулевого указателя * разыменование после очистки памяти * виртуальность деструктора базового класса * использование одного и того же итератора для разных контейнеров * разные более мелкие штуки


Есть возможность помечать классы как умные указатели (чтобы не рапортовало о ложных мемликах), GUI на Qt4.

Vera++

Vera++, в отличие от cppcheck, ориентированна на проверку стиля. Имеет пополняемую базу правил. По умолчанию в базе много реально идиотстких штук типа «перед двоеточием должен быть пробел». Единственная полезная возможность - запрет на использование using namespace в заголовочных файлах. Правила, однако можно писать и самому на языке Tcl. :)

RATS

RATS рассказывает довольно-таки убедительные страшилки про безопасность и buffer overflow-атаки. Не стал пристально разглядывать потому что не очень-то много знаю про защищенный код.

Проверялки для C без плюсов

Удивительно, но программисты на чистом Си, похоже, больше заботятся о статическом анализе. Тут мы имеем список раз и два

Будут ли они полезны плюсовым разработчикам? Если у вас есть код без классов и вы помните, какие программы на C++ не будут собираться компилятором С, то почему бы и нет?

Splint

Вот такая штука для чистого C. Собирается практически без усилий, но работает чистенько и много чего ищет - смотри мануал.

Simian

Simian - similarity analyzer. Ищет дублирование кода, значит. Честно говоря, я не придумал ей применения

CIL

CIL - С Intermediate Language. Компилирует C в упрощенный C! Упрощенный C уже можно скармливать другим анализаторам, что теоретически должно повышать качество их работы.

Непонятное, офтопное
* Oink. Будьте осторожны, если захотите это юзать. При компиляции мне показалось, что я собираю как минимум ядро linux для какой-нибудь экзотической архитектуры. требует Flex и Bison, долго догадывался… (: А еще надо фиксить кучу ошибок при компиляции - такое впечатление, что разработчики свое детище не то, что никогда не запускают - не собирали ни разу. В конце концов зверя одолел, а вот | список фич оказался отнюдь не внушительным. Работает с файлами препроцессора, но выдает по ним какую-то чушь: натравив на простую ошибку с границей массива - получаю тишину. Если же скормить oink'у что-нибудь на C++ с STL - он разразится тирадой на много-много строк. И это я получил ценой 3 часов компиляния и правки исходников? * Mozilla Dehydra - нечто, базируещееся на этом самом Oink'е. Буду рад, если кто-нибудь расскажет об этой чекалке, ибо слово Mozilla в этот раз отнюдь не означало «все просто и понятно». Список находимых багов не увидел, компилять не хотелось после Oink'a. * Еще есть компиляторы, которые предоставляют больше ворнингов на основе статического анализа. Например Rose * Rational Purify - прославленная компания IBM Rational имеет свой набор инструментов для статического и динамического анализа. Буду рад, если кто-нибудь расскажем об этой программе, триальник для линукса у них оказался только для x64-архитектуры.



Триальное/крякнутое ПО

А мало его такого. Много анализаторов, стоящих много долларов и не имеют кряков.
Вот пример такого анализатора, можно зайти на их сайт и попросить триальник Cleanscape. Возможности не сильно отличаются от cppcheck.

Что бы еще хотелось

Не все ошибки в коде, поддающиеся статическому анализу, были представлены в существующих программах. А хотелось бы:
* Политику спецификации исключений как в Java. * использование auto_ptr в контейнерах STL, разыменование auto_ptr после присвоения другому auto_ptr. * using namespace в h-файлах * переопределенный delete без new или new без delete * вызов delete[] для немассивов * использование vector с bool-значениями внутри

Си: C/C++   Теги:

Читать IT-новости в Telegram
Информационные технологии
Мы в соцсетях ✉