V002. Some diagnostic messages may contain incorrect line number.


Иногда анализатор кода может выдавать ошибку "Some diagnostic messages may contain incorrect line number". Это может происходить при использовании многострочных #pragma директив на всех поддерживаемых версиях Microsoft Visual Studio.

Любой анализатор кода работает только с препроцессированными файлами. То есть с теми файлами, в которых раскрыты все макросы (#define) и подставлены все включаемые файлы (#include). При этом в препроцессированном файле содержится информация о том, какие файлы куда подставились и в какие позиции. То есть в пропроцессированных файлах содержится информация о номерах строк.

Препроцессирование выполняется в любом случае. Для пользователя эта процедура выглядит прозрачно. Иногда препроцессор является частью анализатора кода, а иногда (как в случае с PVS-Studio) используется внешний препроцессор. В PVS-Studio используется препроцессор от Microsoft Visual Studio или Clang. Анализатор запускает для каждого обрабатываемого Си/Си++ файла компилятор командной строки cl.exe/clang.exe и генерирует с его помощью препроцессированный файл с расширением "i".

Рассмотрим ситуацию, при которой выдается сообщение "Some diagnostic messages may contain incorrect line number" и происходит сбой в позиционировании диагностических сообщений. Речь идет о многострочных директивах #pragma специального вида. Вот пример корректного кода:

#pragma warning(push) 
void test()
{
  int a;
  if (a == 1) // PVS-Studio сообщит об ошибке здесь
    return;
}

Если же директиву #pragma записать в две строки, то анализатор PVS-Studio может указать на ошибку в неправильном месте (будет сбой на одну строку):

#pragma \
  warning(push) 
void test()
{
  int a;      // PVS-Studio укажет на ошибку здесь,
  if (a == 1) // хотя реально ошибка должна быть здесь.
    return;  
}

Хотя в другом случае с многострочной директивой #pragma ошибки не будет:

#pragma warning \
  (push) 
void test()
{
  int a;
  if (a == 1) // PVS-Studio сообщит об ошибке в этой строке
    return;
}

Наши рекомендации - это либо не использовать многострочные директивы #pragma, либо использовать, но в том варианте, в котором они корректно обрабатываются.

Анализатор кода пытается обнаружить сбой с нумерацией строк в обрабатываемом файле. Этот механизм эвристический и не может гарантировать правильного определения позиционирования диагностических сообщений в коде программы. Но если удается понять, что конкретный файл содержит многострочные директивы #pragma и есть ошибка позиционирования, то и выдается сообщение: "Some diagnostic messages may contain incorrect line number".

Этот механизм работает следующим образом.

Анализатор открывает исходный Си/Си++ файл, и ищет самую последнюю лексему. Выбираются только лексемы не короче трех символов, чтобы игнорировать закрывающиеся скобки и так далее. Например, для следующего кода последней лексемой будет считаться оператор "return":

01 #include "stdafx.h"
02
03 int foo(int a)
04 {
05   assert(a >= 0 &&
06          a <= 1000);
07   int b = a + 1;
08   return b;
09 }

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

Итак, мы имеем номера строк, где расположена последняя лексема в исходном файле и в препроцессированном файле. Если эти номера строк не совпадают, то произошел сбой в нумерации строк. И в данном случае анализатор предупредит об этом пользователя сообщением "Some diagnostic messages may contain incorrect line number".

Следует учитывать, что если многострочная #pragma-директива будут находиться в файле ниже всех найденных опасных участков кода, то все номера строк для найденных ошибок будут корректны. И хотя анализатор выдаст сообщение "Some diagnostic messages may contain incorrect line number for file", это не помешает вам проанализировать выданные им диагностические сообщения.

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


Найденные ошибки

Проверено проектов
361
Собрано ошибок
13 417

А ты совершаешь ошибки в коде?

Проверь с помощью
PVS-Studio

Статический анализ
кода для C, C++, C#
и Java

goto PVS-Studio;