Pull to refresh
612
17
Андрей Карпов @Andrey2008

Директор по развитию бизнеса

Send message

Не очень понятная дискуссия :). Я ведь не то, чтобы спорю :). "Творческий" в том плане, что провоцирует большее количество ошибок, связанных с невнимательностью. Хотя формально разницы нет, будет истина 1 или -1.

Это интересный комментарий, который я использую при случае для написания статьи. Спасибо за тему для дискуссии :).

Статический анализ работает не так. Его задача не в том, чтобы отличать некомпилируемый код от компилируемого. С этим отлично справляются компиляторы. Смысл состоит в поиске синтаксически корректных конструкций, которые с большой вероятностью работают не так, как планировалось, или вообще не работают.

Например, код вида:

if (A == A)

компилируется, однако почти наверняка он ошибочен. О наличии такого кода и должен предупредить статический анализатор кода (V501). И благодаря тому, что анализатор обращает внимание на такой, корректный с точки зрения компилятора код, можно выявить множество ошибок. Да, есть экзотическое использование такой конструкции для проверки float/double переменных на равенство NaN. Но это особый случай, про который статические анализаторы тоже в курсе (по крайней мере, про это знает PVS-Studio).

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

Вариант 1. Код ошибочек и его нужно исправить.

Вариант 2. Код корректен, но с запахом. В этом случае лучше провести рефакторинг. Например написать так:

bool a1 = a != 0;

Вариант 3. Это действительно ложное срабатывание. Его можно подавить различными способами.

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

Например, вот случай, когда явное присваивание в переменную типа bool значения, выходящего за диапазон [0..1], свидетельствует о настоящей ошибке. Я нашёл это в ОС Tizen.

typedef enum {
  BT_PROXIMITY_LINKLOSS_ALERT = 0x01,
  BT_PROXIMITY_IMMEDIATE_ALERT = 0x02,
  BT_PROXIMITY_TX_POWER = 0x04,
} bt_proximity_property_t;

typedef struct {
  bt_proximity_reporter_server_s reporter_server;
  bool services_supported;                                 // <=
  bool connected;

  const void *connection_callback;
  void *user_data;
} bt_proximity_reporter_s;

static bt_proximity_reporter_s *reporter_s = NULL;

int bt_proximity_reporter_create(....)
{
  ....
  reporter_s->services_supported =                         // <=
    BT_PROXIMITY_LINKLOSS_ALERT | BT_PROXIMITY_IMMEDIATE_ALERT;
  ....
}

Хотели записать значение в переменную reporter_server, но промахнулись. И записали в переменную services_supported типа bool.

По поводу виртуальных функций. Эта известная тема. Классика хождения по граблям. У нас даже вопрос на собеседовании есть про вызов виртуальные функции в деструкторе. Ибо опасная тема. И хорошо, если анализатор предложит перепроверить такой код.

Согласен. Но обычно воспринимается это так.

Да, всё верно. Подтверждаю, ругаться на такие выражения как if (result) смысла нет. Собственно, PVS-Studio на них и не ругается (и для C для C++). Слишком много срабатываний.

Хотя нет, есть например, вот такой вариант аномальной проверки: if (enum_var) V768. Но эта другая история.

К сожалению, не понял этот комментарий и вообще эту ветку обсуждения. При чём здесь упаковка и т.д... Да, бывают "особые" boolean типы. Например, существует творческий VARIANT_BOOL, для которого истина задаётся как -1. Однако, это отдельная история, не имеющая отношения к bool.

Правила преобразования bool чётки и понятны. Однако, некоторые из таких преобразований странны и могут являться признаком наличия в коде ошибки. Такой странностью является запись в переменную bool значения отличного от 0/1/false/true. Именно аномальные преобразования и хочет обнаруживать человек, задающий вопрос.

Даже если логика кода верна, то всё равно лучше явно писать что-то в духе:

bool a1 = a != 0;

Исправили. Спс.

Банальную ошибку

Ну это как посмотреть. Проблема остановки:

Проблема остановки (англ. Halting problem) — это одна из проблем в теории алгоритмов[1], которая может неформально быть поставлена в виде:

Даны описание процедуры и её начальные входные данные. Требуется определить: завершится ли когда-либо выполнение процедуры с этими данными; либо, что процедура всё время будет работать без остановки.

Алан Тьюринг доказал в 1936 году, что проблема остановки неразрешима на машине Тьюринга. Другими словами, не существует общего алгоритма решения этой проблемы.[2]

Да. Но как уже отметили, тогда уж надо ещё и умножение длины на sizeof для красоты писать.

Чисто теоретически, легче будет переделать на wchar_t.

Почему зря? Мне кажется, такой вариант смотрится лучше: (len1+len2+1)*sizeof(char). А до этого смешивалось понятие длины строк и размера терминально символа.

Согласен. Поменял в статье.

Интересно, PVS-Studio справится с такой задачей, что скажет Andrey2008?

К сожалению, пока нет. Выписал для будущих доработок dataflow.

Сейчас таких планов нет.

Information

Rating
434-th
Works in
Date of birth
Registered
Activity

Specialization

Specialist
C++
C
Software development