Меня попросили проверить логику вывода движка в логике описания приложения factplusplus. Итак, я посмотрел проект. Он был небольшим, его плотность ошибок — низкая. Так что в целом все выглядело хорошо. По крайней мере, я не нашел ничего, что стоило бы писать статью. Я даже не планировал писать публичный ответ. Но, разговаривая с человеком через сообщения на Хабре, я понял, что это не удобно — я пытался вставить код в сообщение, и оно оказалось не таким организованным, как хотелось бы. Поэтому я решил написать здесь мини-пост и отправить ссылку человеку.

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

Однако есть несколько вещей, которые я заметил:

Опечатка. PVS-Studio предупреждает: V524 Странно, что тело функции p_begin полностью эквивалентно телу функции s_end. ТаксономияCreator.h 82

ss_iterator s_begin ( void ) override { return beg; }
ss_iterator s_end ( void ) override { return end; }
ss_iterator p_begin ( void ) override { return end; }      // <=
ss_iterator p_end ( void ) override { return end; }

Оператор new явно лишний. PVS-Studio предупреждает: V1022 [CWE-755] Исключение было вызвано указателем. Вместо этого попробуйте бросить его по значению. Расширенныйдатаранж.cpp 44

static bool
checkDataRelation ( const DataTypeReasoner& Op1, const DataTypeReasoner& Op2, int op )
{
  switch (op)
  {
  ....
  default:
    throw new EFaCTPlusPlus("Illegal operation in checkDataRelation()");
  }
}

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

if ( value == nullptr )
  parseError("Data value expected");
TDataTypeExpr* type = const_cast<TDataTypeExpr*>(value->getExpr());

Анализатор предупреждает, что здесь происходит разыменование нулевого указателя: V522 [CWE-690] Возможно, происходит разыменование потенциального значения нулевого указателя. parser.cpp 611

Причина в том, что функция

void parseError ( const char* p )

не помечен как возвращающий управление. Если вы измените его на

[[noreturn]] void parseError ( const char* p )

предупреждение исчезает. И код становится понятнее и легче читается.

Это все. Приглашаю всех в наш блог, где мы проверяем различные проекты и пишем о любопытных вещах, которые там находим.