Иногда анализатор кода PVS-Studio может выдавать следующую ошибку: "Some diagnostic messages may contain incorrect line number for file ...". Такое может происходить, если вы используете Microsoft Visual Studio 2005 без обновления Visual Studio Service Pack 1. Это именно ошибка (error), а не диагностическое сообщение (warning). В этой заметке мы расскажем, что это за сообщение и как на него реагировать.
Любой анализатор кода, и PVS-Studio здесь не исключение, работает только с препроцессированными файлами. То есть с теми файлами, в которых раскрыты все макросы (define) и подставлены все включаемые файлы (#include). При этом в препроцессированном файле содержится информация о том, какие файлы куда подставились и в какие позиции. То есть в пропроцессированных файлах содержится информация о номерах строк.
Препроцессирование выполняется в любом случае. Но для пользователя эта процедура выглядит прозрачно. Иногда препроцессор является частью анализатора кода, а иногда (как в случае с PVS-Studio) используется внешний препроцессор. В PVS-Studio мы используем препроцессор от Microsoft Visual Studio. Анализатор запускает для каждого обрабатываемого Си/Си++ файла компилятор командной строки cl.exe и генерирует с его помощью препроцессированный файл с расширением "i".
В препроцессоре от Microsoft Visual Studio 2005 есть ошибка. Если выполнять препроцессирование из командной строки (как делается в PVS-Studio), то при наличии в коде программы многострочных макросов информация о номерах строк сбивается. Это может привести к некорректному позиционированию анализатора кода в файле. То есть анализатор кода найдет реальную проблему, но строку, в которой эта проблема обнаружена, укажет неверно.
Поясним на примере. В простом коде используется assert, причем выражение в скобках разбито на несколько строк. Например, так:
int _tmain(int argc, _TCHAR* argv[])
{
int a = 0;
int b = 1;
size_t c = 2;
assert(a ==
b);
a++; // Анализатор покажет ошибку в этой безобидной строке.
c = a; // Хотя реально диагностическое сообщение должно
// указывать на строку "c = a;".
return 0;
}
Как видно в комментариях, из-за наличия многострочного assert анализатор покажет, что ошибка есть (это правильно), но в качестве строки, содержащей эту ошибку, укажет строку выше. Естественно это может ввести пользователя в заблуждение.
Если тот же самый код записать с assert в одну строку, то проблемы не будет:
int _tmain(int argc, _TCHAR* argv[])
{
int a = 0;
int b = 1;
size_t c = 2;
assert (a == b);
a++;
c = a; // Диагностическое сообщение ссылается на
// правильную строку.
return 0;
}
Эта ошибка проявляется только при работе PVS-Studio на Microsoft Visual Studio 2005 без пакета обновлений Visual Studio Service Pack 1. На Visual Studio 2005 Service Pack1, а также на более старших версиях (Visual Studio 2008 и выше) этой проблемы нет. В качестве решения мы рекомендуем установить на Visual Studio 2005 пакет обновлений Visual Studio 2005 Service Pack 1. Тогда код с многострочными макросами будет обрабатываться анализатором PVS-Studio корректно.
Однако бывают ситуации, когда установить Visual Studio 2005 Service Pack 1 не представляется возможным по каким-то причинам. В этом случае анализатор PVS-Studio пытается обнаружить такую ошибку в обрабатываемом файле. Этот механизм эвристический и не может гарантировать правильного определения позиционирования диагностических сообщений в коде программы. Но если удается понять, что конкретный файл содержит многострочные макросы и есть ошибка позиционирования, то и выдается сообщение: "Some diagnostic messages may contain incorrect line number for file ...".
Этот механизм работает следующим образом.
Анализатор открывает исходный Си/Си++ файл, и ищет самую последнюю лексему. Выбираются только лексемы не короче трех символов, чтобы игнорировать закрывающиеся скобки и так далее. Например, для следующего кода последней лексемой будет считаться оператор "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 for file ...".
Следует учитывать, что если многострочный assert или иной многострочный макрос будет находиться в файле ниже всех найденных опасных участков кода, то все номера строк для найденных ошибок будут корректны. И хотя анализатор выдаст сообщение "Some diagnostic messages may contain incorrect line number for file ...", это не помешает вам проанализировать выданные им диагностические сообщения.
Обратим внимание, что хотя это и не ошибка непосредственно анализатора кода PVS-Studio, тем не менее, это приводит к некорректной работе анализатора кода. Наилучшим решением проблемы является установка Microsoft Visual Studio 2005 Service Pack 1.