Статический анализ кода: современный взгляд Карпов Андрей Николаевич к.ф.-м.н., технический директор ООО «Системы программной верификации» E-mail: karpov@viva64.comkarpov@viva64.

Презентация:



Advertisements
Похожие презентации
Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.
Advertisements

Обработка исключений Основы метапрограммированияОбработка исключений Основы метапрограммирования.
Инструкции C++ Условная инструкция Формат: if (условие) оператор; else оператор; Пример: if (i!=0) { if (j) j++; if(k) k++; else if(p) k--; } else i--;
Д.з Язык С++ - занятие 31. Задача 1: 1/1 + 1/3 + 1/5 … #include using namespace std; int main() { int n; cin >> n; double sum = 0;// Сумма for.
ООО «Системы программной верификации» Конференция CEE-SECR 2009 Авторы:Карпов Андрей Рыжков Евгений.
С++, ООП Семинар 2 Рябова Анна Сергеевна
Преобразования типов В языке C/C++ имеется несколько операций преобразования типов. Они используются в случае, если переменная одного типа должна рассматриваться.
Наследование Наследование – это отношение является между классами. class Person { string first_name; int birth_year;... } class Student : Person { float.
Символы и строки 1. Содержание 8.1Введение 8.2Основы Строк и Символов 8.3Библиотека работы со строками 8.4Преобразование строк 8.5Стандартная библиотека.
Объектно-ориентированное программирование С++. Лекция 9 Карпов В.Э.
ПРОГРАММИРОВАНИЕ/ ЯЗЫКИ ПРОГРАММИРОВАНИЯ Лекция 4 Работа с бинарными файлами (весенний семестр 2012 г.) Доцент Кафедры вычислительных систем, к.т.н. Поляков.
Проблема переноса приложений на 64-битные платформы Процесс миграции кода неизбежен. Миграция C/C++ приложений.
Лекция 9 Функции. Массивы-параметры функции Передача массива в функцию Пример: void array_enter(int a[], int size) { int i; for (i = 0; i < size; i++)
УКАЗАТЕЛИ. Переменная - это именованная область памяти с заданным типом. [=значение]; int a; //Переменная типа integer с именем a int b=2;// Переменная.
1. Классы ООП 1.Наследование 2.Инкапсуляция 3.Полиморфизм.
ООП Классы Данные отдельно, методы отдельно struct Node { Node* next; void* data; }; struct List { Node* first; int size; }; void* allocate() { … } void.
Высокоуровневые методы информатики и программирования Лекция 14 Интерфейсы.
ООП Классы – 2.
Лекция 3. Введение в C++ Примеры взяты из книги Брюса Эккеля Думаем на С++
Лекция 13. Введение в ООП. Часть 4 Красс Александр СПбГУ ИТМО, 2008.
Транксрипт:

Статический анализ кода: современный взгляд Карпов Андрей Николаевич к.ф.-м.н., технический директор ООО «Системы программной верификации» com Program Verification Systems

О чем доклад? Андрей Карпов – сотрудник ООО «Си ПроВер», разработчик статического анализатора кода PVS-Studio; доклад посвящен состоянию дел в области статического анализа Си/Си++ кода; это не сравнение инструментов, а взгляд на развитие отрасли.

Статический анализ это просмотр исходного кода разработчиком в тех местах, где по мнению статического анализатора присутствует неверное оформление или ошибка.

Два основных направления статического анализа Поддержка стандарта кодирования, принятого в компании отступы; именование переменных; правила использование комментариев; … Поиск ошибок в коде неинициализированные переменные; всегда ложные условия; T *p = new T[n]; /* code */ free(p); … Часто « дискредитируют» статический анализ.

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

Классическое. Не используйте комментарии в стиле C: /* … */ Стандарт MISRA предостерегает от использования комментариев в стиле /* … */. Комментарии плохо заметны. Сложнее разобраться в коде, легче допустить ошибку. Вернее были плохо заметны. Не актуально

Есть просто устаревшее Не рекомендуется: wchar_t* x = L"Fred"; // нарушение Рекомендуется: char* x = "Fred"; А вот еще одна из рекомендаций MISRA, реализованная в Parasoft C++test: (misra-008) Do not use wide string literals Не используйте строки в формате wchar_t. Пора рекомендовать наоборот!

Привет из 1992 года… В Pasrasoft C++test присутствует правило, взятое из стандарта кодирования 1992 года: (ellemtel_rule-01) Include files in C++ always have the file name extension ".hh". В С++ файлах должны использоваться заголовочные файлы с расширением ".hh". Не сказал бы, что это повсеместно прижилось… Не рекомендуется: #include "MyClass.h" // нарушение Рекомендуется: #include "MyClass.hh" Не интересно

С некоторыми правилами не поспоришь - но толку от них никакого Pasrasoft C++test: (ellemtel_rule-37) Do not use 'magic numbers Не используйте магические числа. Вообще не используйте! Делайте enum или константы. Не рекомендуется: float rgb[3]; // нарушение n = sizeof(rgb) / sizeof(rgb[0]) // нарушение Рекомендуется: const size_t RgbArraySize = 3; float rgb[RgbArraySize]; enum color { RED = 0, BLUE = 1, GREEN = 2 }; n = sizeof(rgb) / sizeof(rgb[RED]); Формально все верно. Но нерациональные трудозатраты при сомнительной пользе.

Опасно использовать адресную арифметику - не поспоришь В С++Test имеется проверка относящаяся к MISRA: (misra-101) Do not use pointer arithmetic. Не используйте адресную арифметику. Не рекомендуется: int* p; p++; // нарушение int *x = p+5; // нарушение Рекомендуется: не использовать Спасибо за рекомендацию. А что мне с ней делать?

Поиск ошибок тоже устаревает ошибки все лучше выявляются компилятором; многим разработчикам уже не интересны ошибки, связанные с FAR указателями или массивами больше 64-килобайт; мало внимания уделяется использованию библиотек (stl, boost, MFC, Windows API).

Хорошее, но устаревшее правило для диагностики Неправильно: class ClassX { … ClassX(const ClassX x) { m_v = x.m_v; } // нарушение }; Правильно: class ClassX { … ClassX(const ClassX &x) { m_v = x.m_v; } }; При вывозе конструктора копирования возникнет вечный цикл.

Давно реализовано в Visual C++. Даже не компилируется VS2005 сообщает: error C2652: 'ClassX' : illegal copy constructor: first parameter must not be a 'ClassX ClassX(const ClassX x) { m_v = x.m_v; } Хорошо, что это правило 1063 есть и в PC-Lint. На свете еще много неполноценных компиляторов для микроконтроллеров. Но разработчику, использующему Visual Studio 2005/2008/2010 это уже не интересно.

Пример хорошей проверки PC-Lint: 682 В примере «array» является указателем, а не массивом. В 32-битной программе получим значение 1, а не 3. Неправильно: void Foo26(float array[3]) { size_t n = sizeof(array) / sizeof(array[0]); //нарушение Правильно: void Foo26(float *array, size_t array_size) { size_t n = array_size;

Пример хорошей проверки Parasoft C++test: sa-100_DoNotTreatArraysPolymorphically class Class5_Base { int a; }; class Class5 : public Class5_Base { int b; }; void Process5(Class5_Base *p, size_t n) { for (size_t i = 0; i != n; ++i) p[i].a = 22; } Class5 X[5]; Process5(X, 5); //нарушение Через указатель на базовый класс нельзя работать с массивом производных классов, так как классы имеют разный размер.

Пример хорошей проверки PVS-Studio: V512: A call of the 'memset' function will lead to a buffer overflow or underflow. Неправильно: MD5Context *ctx;... memset(ctx, 0, sizeof(ctx)); // нарушение if (memcmp(this, &other, sizeof(Matrix4) == 0)) // нарушение Правильно: MD5Context *ctx;... memset(ctx, 0, sizeof(*ctx)); if (memcmp(this, &other, sizeof(Matrix4)) == 0)

Пример хорошей проверки ~ClassX() { if (!m_init) throw std::exception("Error"); //нарушение free(m_p1); free(m_p2); } PC-Lint: Нельзя бросать исключение из деструктора.

Пример хорошей проверки Parasoft C++test: ecpp-25_ZeroConversionProblem void func(float, int *) { } void func(float, int) { } void F() { Неправильно: func(1.0f, 0); //нарушение func(1.0f, NULL); //нарушение Правильно: func(1.0f, nullptr); } Неожиданное поведение кода из-за выбора не той перегруженной функции.

Пример хорошей проверки Неправильно: class Foo { int iChilds[2];... bool hasChilds() const { return(iChilds > 0 || iChilds > 0); } // нарушение } PVS-Studio: V501. There are identical sub-expressions to the left and to the right of the '||' operator. Слева и справа от оператора ||, &&, ==, 0 || iChilds[1] > 0); }

Пример хорошей проверки Неправильно: HRESULT hr = CoInitialize(NULL); if (!hr) //нарушение Code Analysis for C/C++: Правильно: if (FAILED(hr)) Неправильно: HRESULT hr; hr = TRUE; //нарушение Правильно: #define S_OK ((HRESULT)0L) hr = S_OK; C6217: неявное приведение между семантически различными целочисленными типами: проверка HRESULT с "not". C6225: неявное приведение между семантически различными целочисленными типами: присвоение HRESULT значения 1 или TRUE.

Сам придумал Нигде аналогичной проверки не видел Неправильно: if(radius < THRESH * 5) *yOut = THRESH * 10 / radius; else if (radius < THRESH * 5) //нарушение *yOut = -3.0f / (THRESH * 5.0f) * (radius - THRESH * 5.0f) + 3.0f; else *yOut = 0.0f; Правильно: Затрудняюсь привести верный вариант. PVS-Studio: V517. The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Повторяющиеся условия в конструкции вида "else if".

Состояние дел в области статического анализа Многое из нового делается «для галочки»: –Qt Best Practices Rules; –/Wp64 в Visual C++ – это 10%-15% от того, что позволяет обнаружить Viva64. Хромает поддержка нового и C++0x в частности.

Состояние дел в области статического анализа Gimpel PC-Lint; Parasoft C++test; Coverity; Klocwork; Visual Studio: Code Analysis for C/C++; PVS-Studio.

PVS-Studio: Viva64 – выявление 64-битных ошибок; VivaMP - выявление параллельных ошибок; в разработке современный статический анализатор общего назначения. Скачать PVS-Studio:

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

Вопросы ? Контактная информация: Карпов Андрей Николаевич к.ф.-м.н., технический директор ООО «Системы программной верификации» Сайт: com Тел.: +7 (4872) (GMT + 03:00) Twitter: