>
>
Немного о проверке шаблонов

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

Немного о проверке шаблонов

Иногда анализатор PVS-Studio выдает загадочные сообщения, в которых упоминается шаблонный класс. Вот пример такого сообщения: V614 Instantiate ReconstructMB<PlaneY, PlaneUV, color_format, false, 1>: Uninitialized variable 'iRefFieldTop' used. Встретившись с таким сообщением и рассматривая код шаблонного класса можно загрустить. Всё кажется сложным и непонятным. Но всё не так страшно. Давайте попробуем разобрать один пример.

Рассмотрим фрагмент кода, взятый из реального приложения.

template <typename PlaneY, typename PlaneUV,
          Ipp32s color_format, Ipp32s is_field, Ipp32s is_weight,
          bool nv12_support = false>
class ReconstructMB
{
public:
  ...
  void CompensateMotionChromaBlock(ReconstructParams *pParams,
         Ipp32s iDir, Ipp32s iBlockNumber, Ipp32s iUniDir)
  {
    Ipp32s iRefFieldTop;
    if (is_field)
    {
      if (pParams->is_mbaff)
      {
        iRefFieldTop = pParams->is_bottom_mb ^
                       (pParams->m_iRefIndex[iDir] & 1);
        pParams->m_iRefIndex[iDir] = iRefIndex;
      }
      else
        iRefFieldTop =
          GetReferenceField(pParams->m_pSegDec->m_pFields[iDir],
                            iRefIndex);
      
      if (iRefFieldTop)
      { ..... }
    }
    .....
    interpolateInfo->pointVector.y +=
      (pParams->is_bottom_mb - iRefFieldTop) * 2; // <= V614
    .....
};

В общем, что-то длинное и невразумительное. Разбираться в таком коде не хочется, но анализатор требует обратить на него внимания. Я специально взял такой длинный пример. Хочу показать, что программисту не стоит лениться. Следует постараться понять, что может не нравиться анализатору.

Вот сообщение, выданное PVS-Studio:

V614 Instantiate ReconstructMB<PlaneY, PlaneUV, color_format, false, 1>: Uninitialized variable 'iRefFieldTop' used. umc_h264_reconstruct_templates.h 227

В строке 227 PVS-Studio подозревает использование неинициализированной переменной 'iRefFieldTop'.

Если мы изучим код, то увидим, что переменная 'iRefFieldTop' инициализируется только в том случае, если выполняется условие "if (is_field)". Значение 'is_field' является аргументом шаблона. Тип этого значения 'Ipp32s'.

Естественно, никакой ошибки не возникнет, если класс ReconstructMB будет инстанцироваться со значениями "is_field != 0". Например, как-то так:

ReconstructMB<PlaneY, PlaneUV, color_format, 1, 1, false> X;

Но нет, анализатор предупреждает не зря. Если поискать, то можно найти вот такое забавное объявление переменной:

ReconstructMB<PlaneY, PlaneUV, color_format, false, 0> mb;

Видно, что здесь что-то напутано. Смотрите, что ожидается и что передаётся:

Аргументы шаблона      Аргументы при объявлении переменной
typename PlaneY                      PlaneY
typename PlaneUV                     PlaneUV
Ipp32s color_format                  color_format
Ipp32s is_field                      false
Ipp32s is_weight,                    0
bool nv12_support = false            (none)

Странно, что один аргумент типа 'Ipp32s' задаётся равным '0', а другой равным 'false'. Очень странный стиль программирования!

Скорее всего, в процессе рефакторинга добавлялись или изменялись параметры шаблона. А в этом месте забыли исправить объявление переменной 'mb'. Код компилировался, и никто не заметил опасности.

В общем-то, не так важно, как получился такой код. Важно то, что в программе есть использование неинициализированной памяти. И анализатор PVS-Studio это обнаружил. При этом в сообщении он указал, что ошибка возникнет, когда класс инстанцируется следующим образом: ReconstructMB<PlaneY, PlaneUV, color_format, false, 1>.

Надеюсь, я разъяснил, что означают подобные сообщения анализатора и какую информацию они содержат.

Желаю вам повышения надёжности от использования анализатора PVS-Studio!