Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
GBP
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
>
Почему я не люблю синтетические тесты

Почему я не люблю синтетические тесты

06 Фев 2017

Мне не нравится, когда кто-то пытается использовать созданные вручную примеры кода для оценки возможностей статического анализатора кода. Сейчас на конкретном примере я продемонстрирую, почему негативно отношусь к синтетическим тестам.

0471_Why_I_Dislike_Synthetic_Tests_ru/image1.png

Не так давно Bill Torpey написал в своем блоге заметку "Even Mo' Static", где рассказал, как, на его взгляд, показали себя инструменты Cppcheck и PVS-Studio при анализе проекта itc-benchmarks. Проект itc-benchmarks - это static analysis benchmarks from Toyota ITC.

Мне не понравилось, что после прочтения статьи создается впечатление, что анализаторы Cppcheck и PVS-Studio приблизительно равны в своих возможностях. Из статьи следует, что один анализатор показывает себя лучше в одном, второй в другом, но в целом их диагностические возможности похожи.

Я думаю, что это не так. Мое мнение - наш анализатор PVS-Studio в несколько раз мощнее, чем Cppcheck. И вообще, это не "мнение", я знаю это!

Однако, раз со стороны не видно, что PVS-Studio в 10 раз лучше Cppcheck, то надо попытаться понять причину. Я решил посмотреть на этот самый itc-benchmarks и разобраться, почему PVS-Studio показал себя на этой тестовой базе не лучшим образом.

Чем дальше я разбирался, тем большее раздражение я испытывал. А один пример совсем вывел меня из равновесия, и о нем я расскажу чуть ниже. Мои выводы такие: у меня нет претензий к Bill Torpey. Он написал хорошую, честную статью. Спасибо, Bill. Зато у меня есть претензии к Toyota ITC. Мое личное мнение: их тестовая база - хрень. Это, конечно, громкое заявление, но я считаю, что имею достаточную квалификацию и опыт, чтобы рассуждать о статических анализаторах кода и способах их оценки. По моему мнению, itc-benchmarks не может быть использован для адекватной оценки возможностей того или иного анализатора.

А вот собственно тест, который окончательно вывел меня из душевного равновесия.

Это тест на разыменование нулевого указателя:

void null_pointer_001 ()
{
  int *p = NULL;
  *p = 1; /*Tool should detect this line as error*/
          /*ERROR:NULL pointer dereference*/
}

Анализатор Cppcheck заявляет, что нашел ошибку в этом коде:

Null pointer dereference: p

Анализатор PVS-Studio на этом коде молчит, хотя для таких случаев в нём существует диагностика V522.

Так что же получается, PVS-Studio на этом примере слабее чем Cppcheck? Нет, он как раз сильнее!

Анализатор PVS-Studio понимает, что этот код написан сознательно и никакой ошибки здесь нет.

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

void GpuChildThread::OnCrash() {
  LOG(INFO) << "GPU: Simulating GPU crash";
  // Good bye, cruel world.
  volatile int* it_s_the_end_of_the_world_as_we_know_it = NULL;
  *it_s_the_end_of_the_world_as_we_know_it = 0xdead;
}

Поэтому в анализаторе PVS-Studio в диагностике V522 реализовано несколько исключений, чтобы как раз не ругаться на такой код. Анализатор видит, что null_pointer_001 является ненастоящей функцией. Не бывает в реальном коде ошибок в функциях, когда ноль записывают в указатель и сразу его разыменовывают. Да и имя функции говорит анализатору, что "нулевой указатель" здесь неспроста.

Для подобных случаев, в диагностике V522 реализовано исключение A6. Под него же попадает и синтетическая функция null_pointer_001. Вот как опасно исключение A6:

Разыменование переменной находится в функции, в названии которой есть одно из слов:

  • error
  • default
  • crash
  • null
  • test
  • violation
  • throw
  • exception

При этом, переменной присваивается 0 строчкой выше.

Синтетический тест полностью подошел под это исключение. Во-первых, в названии функции есть слово "null". Во-вторых, присваивание нуля переменной происходит как раз на предыдущей строке. Исключение выявило ненастоящий код. И код действительно не настоящий, это синтетический тест.

Вот из-за подобных нюансов я и не люблю синтетические тесты!

У меня есть к itc-benchmarks и другие претензии. Например, всё в том же файле, мы можем видеть вот такой тест:

void null_pointer_006 ()
{
  int *p;
  p = (int *)(intptr_t)rand();
  *p = 1; /*Tool should detect this line as error*/
          /*ERROR:NULL pointer dereference*/
}

Функция rand может вернуть 0, который затем превратится в NULL. Анализатор PVS-Studio пока не знает, что может вернуть rand и поэтому не видит в этом коде ничего подозрительного.

Я попросил коллег научить анализатор лучше понимать, что из себя представляет функция rand. Деваться некуда, придётся подточить напильником анализатор, чтобы он лучше себя показывал на рассматриваемой тестовой базе. Это вынужденная мера, раз для оценки анализаторов используют подобные наборы тестов.

Но не бойтесь. Я заявляю, что мы по-прежнему будем работать над настоящими хорошими диагностиками, а не заниматься подгонкой анализатора под тесты. Пожалуй, мы немного подретушируем PVS-Studio для itc-benchmarks, но в фоновом режиме и только в тех местах, которые имеют хоть какой-то смысл.

Я хочу, чтобы разработчики понимали, что пример с rand ничего на самом деле не оценивает. Это синтетический тест, который высосан из пальца. Не пишут так программы. Нет таких ошибок.

Кстати, если функция rand вернёт не 0, а 1400 лучше не будет. Все равно такой указатель разыменовывать нельзя. Так что разыменование нулевого указателя какой-то странный частный случай совершенно некорректного кода, который просто был выдуман и который не встречается в реальных программах.

Мне известны настоящие программистские беды. Например, это опечатки, которые мы выявляем сотнями, скажем, с помощью диагностики V501. Что интересно, в itc-benchmarks я не заметил ни одного теста, где проверялось, может ли анализатор обнаружить опечатку вида "if (a.x == a.x)". Ни одного теста!

Таким образом, itc-benchmarks игнорирует возможности анализаторов по поиску опечаток. А читатели наших статей знают, насколько это распространенные ошибки. Зато содержит, на мой взгляд, дурацкие тестовые кейсы, которые в реальных программах не встречаются. Я не могу представить, что в настоящем серьезном проекте можно повстречать вот такой код, который приводит к выходу за границу массива:

void overrun_st_014 ()
{
  int buf[5];
  int index;
  index = rand();
  buf[index] = 1; /*Tool should detect this line as error*/
                  /*ERROR: buffer overrun */
  sink = buf[idx];
}

Пожалуй, такое можно встретить разве только в лабораторных работах студентов.

При этом я знаю, что в серьезном проекте легко встретить опечатку вида:

return (!strcmp (a->v.val_vms_delta.lbl1,
                 b->v.val_vms_delta.lbl1)
        && !strcmp (a->v.val_vms_delta.lbl1,
                    b->v.val_vms_delta.lbl1));

Эту ошибку анализатор PVS-Studio нашел в коде компилятора GCC. Два раза сравниваются одни и те же строки.

Получается, что тесты на поиск экзотического кода с rand есть, а на классические опечатки нет.

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

Предлагаю всем установить и попробовать мощнейший анализатор кода PVS-Studio.

Дополнительные ссылки:

Популярные статьи по теме
Статический анализ как часть процесса разработки Unreal Engine

Дата: 27 Июн 2017

Автор: Андрей Карпов

Проект Unreal Engine развивается - добавляется новый код и изменятся уже написанный. Неизбежное следствие развития проекта - появление в коде новых ошибок, которые желательно выявлять как можно раньш…
Характеристики анализатора PVS-Studio на примере EFL Core Libraries, 10-15% ложных срабатываний

Дата: 31 Июл 2017

Автор: Андрей Карпов

После большой статьи про проверку операционной системы Tizen мне было задано много вопросов о проценте ложных срабатываний и о плотности ошибок (сколько ошибок PVS-Studio выявляет на 1000 строк кода)…
PVS-Studio ROI

Дата: 30 Янв 2019

Автор: Андрей Карпов

Время от времени нам задают вопрос, какую пользу в денежном эквиваленте получит компания от использования анализатора PVS-Studio. Мы решили оформить ответ в виде статьи и привести таблицы, которые по…
Главный вопрос программирования, рефакторинга и всего такого

Дата: 14 Апр 2016

Автор: Андрей Карпов

Вы угадали, ответ - "42". Здесь приводится 42 рекомендации по программированию, которые помогут избежать множества ошибок, сэкономить время и нервы. Автором рекомендаций выступает Андрей Карпов - тех…
Любите статический анализ кода!

Дата: 16 Окт 2017

Автор: Андрей Карпов

Я в шоке от возможностей статического анализа кода, хотя сам участвую в разработке инструмента PVS-Studio. На днях я был искренне удивлён тому, что анализатор оказался умнее и внимательнее меня.
Как PVS-Studio оказался внимательнее, чем три с половиной программиста

Дата: 22 Окт 2018

Автор: Андрей Карпов

PVS-Studio, как и другие статические анализаторы кода, часто выдаёт ложные срабатывания. Но не стоит спешить считать странные срабатывания ложными. Это короткая история о том, как PVS-Studio вновь ок…
Технологии, используемые в анализаторе кода PVS-Studio для поиска ошибок и потенциальных уязвимостей

Дата: 21 Ноя 2018

Автор: Андрей Карпов

Краткое описание технологий, используемых в инструменте PVS-Studio, которые позволяют эффективно обнаруживать большое количество паттернов ошибок и потенциальных уязвимостей. Статья описывает реализа…
Бесплатный PVS-Studio для тех, кто развивает открытые проекты

Дата: 22 Дек 2018

Автор: Андрей Карпов

В канун празднования нового 2019 года команда PVS-Studio решила сделать приятный подарок всем контрибьюторам open-source проектов, хостящихся на GitHub, GitLab или Bitbucket. Им предоставляется возмо…
Как и почему статические анализаторы борются с ложными срабатываниями

Дата: 20 Мар 2017

Автор: Андрей Карпов

В своей предыдущей статье я писал, что мне не нравится подход, при котором статические анализаторы кода оцениваются с помощью синтетических тестов. В статье приводился пример, воспринимаемый анализат…
PVS-Studio для Java

Дата: 17 Янв 2019

Автор: Андрей Карпов

В седьмой версии статического анализатора PVS-Studio мы добавили поддержку языка Java. Пришло время немного рассказать, как мы начинали делать поддержку языка Java, что у нас получилось и какие дальн…

Комментарии (0)

Следующие комментарии

На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Этот сайт использует куки и другие технологии, чтобы предоставить вам более персонализированный опыт. Продолжая просмотр страниц нашего веб-сайта, вы принимаете условия использования этих файлов. Если вы не хотите, чтобы ваши данные обрабатывались, пожалуйста, покиньте данный сайт. Подробнее →
Принять