Lt304888.ru

Туристические услуги

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

10-07-2023

Стати́ческий ана́лиз ко́да (англ. static code analysis) — анализ программного обеспечения, производимый без реального выполнения исследуемых программ (анализ, производимый с выполнением программ, называется динамический анализ кода). В большинстве случаев анализ производится над какой-либо версией исходного кода, хотя иногда анализу подвергается какой-нибудь вид объектного кода, например P-код или код на MSIL. Термин обычно применяют к анализу, производимому специальным ПО, тогда как ручной анализ называют пониманием или постижением программы.

В зависимости от используемого инструмента глубина анализа может варьироваться от определения поведения отдельных операторов до анализа, включающего весь имеющийся исходный код. Способы использования полученной в ходе анализа информации также различны — от выявления мест, возможно содержащих ошибки, до формальных методов, позволяющих математически доказать какие-либо свойства программы (например, соответствие поведения спецификации).

Некоторые люди считают программные метрики и обратную разработку формами статического анализа.

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

Содержание

Принципы статического анализа

Большинство современных компиляторов (например, GNU C Compiler) выводят на экран «предупреждения» (англ. warnings) — сообщения о том, что код, будучи формально правильным, скорее всего, содержит ошибку. Например:

int x;
int y = x+2;    // Переменная x не инициализирована!
int someFunc(long& x)    {  ...  }
 
short a = 5;
someFunc(long(a));   // Временная переменная long(a) будет потеряна!

Это тоже простейший статический анализ. Но у компилятора есть много других немаловажных характеристик — скорость работы, качество машинного кода, удобство… Да и «зашумлять» консоль ложными тревогами — не самое удачное решение. Поэтому компиляторы проверяют код лишь на простейшие, очевидные ошибки. А для более серьёзного исследования кода есть специализированное ПО, запускаемое не постоянно, а лишь время от времени.

Статические анализаторы кода могут проверять на такие ошибки:

Явные случаи неопределённого поведения 
Неинициализированные переменные, обращение к NULL-указателям и т. д. О простейших из этих случаев сигнализируют даже компиляторы.
Нарушение блок-схемы пользования библиотекой 
Для каждого fopen нужен fclose. И если файловая переменная теряется раньше, чем файл закрывается, анализатор может сообщить об ошибке.
Типичные сценарии, приводящие к недокументированному поведению 
Стандартная библиотека языка Си известна огромным количеством неудачных технических решений. Некоторые функции, например, gets, в принципе небезопасны. sprintf и strcpy безопасны лишь при определённых условиях. И, например, статический анализатор может обратить внимание программиста на такой код.
void doSomething(const char* x)
{
    char s[40];
    sprintf(s, "[%s]", x);    // sprintf в локальный буфер, возможно переполнение
    ....
}
Типичные сценарии, мешающие кроссплатформенности 
Разные платформы — это совсем разные «миры». Языки, конечно же, стараются делать кроссплатформенными, но программисты под ту или иную платформу привыкли упрощать код, одновременно привязывая его к «своей» плафторме. Например:
Object *p = getObject();
int pNum = reinterpret_cast<int>(p);    // на x86-32 верно, на x64 часть указателя будет потеряна; нужен size_t
Прочие ошибки по невнимательности 
Например, многие функции из стандартных библиотек не имеют побочного эффекта, и вызов их как процедур не имеет смысла. Так что ошибочным будет код[1]
std::string s;
...
s.empty();     // код ничего не делает; вероятно, вы хотели s.clear()?
Даже в самом пуританском коде есть частично повторяющиеся фрагменты. Обычно их не пишут с нуля, а размножают и исправляют. Получаются ошибки наподобие:
dest.x = src.x + dx;
dest.y = src.y + dx;  // Ошибка, надо dy!
В функциях наподобие printf могут быть ошибки с несоответствием форматной строки реальному типу параметров[1]:
std::wstring s;
printf ("s is %s", s);
Неизменный параметр, передаваемый в функцию 
Иногда подобные «брошенные» параметры — признаки изменившихся требований к программе: когда-то параметр был задействован, но сейчас он уже не нужен. В таком случае программист может вообще избавиться от этого параметра — и от связанной с ним логики.
void doSomething(int n, bool flag)   // flag всегда равен true
{
   if (flag)
   {
       // какая-то логика
   } else
   {
       // код есть, но не задействован
   }
}
 
doSomething(n, true);
...
doSomething(10, true);
...
doSomething(x.size(), true);

Формальные методы

Инструменты статического анализа

  • BLAST
  • Coverity
  • [2]
  • lint и lock_lint, входящие в состав Sun Studio
  • MSR Tools
  • Parasoft C++Test, JTest
  • ReSharper
  • Sonar
  • SourceAnalyzer
  • Svace Detector
  • T-SQL Analyzer — инструмент, который может просматривать программные модули в базах данных под управлением Microsoft SQL Server 2005 или 2008 и обнаруживать потенциальные проблемы, связанные с низким качеством кода.
  • АК-ВС

См. также

Примечания

  1. ↑ [1]

Ссылки

  • Скринкаст: Статический анализ Си++ кода
  • О безошибочных программах
  • Первые шаги к решению проблемы верификации программ
  • Сертификация и тестирование программного обеспечения
  • Что такое «Parallel Lint»?


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

© 2020–2023 lt304888.ru, Россия, Волжский, ул. Больничная 49, +7 (8443) 85-29-01