>
>
>
V1001. Variable is assigned but not use…


V1001. Variable is assigned but not used by the end of the function.

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

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

Пример 1.

bool IsFitRect(TPict& pict)
{
  TRect pictRect;
  ...
  pictRect = pict.GetRect();
  return otherRect.dx >= 16 && otherRect.dy >= 16;
}

В этом примере в операторе 'return' вместо размеров 'pictRect' по ошибке используются размеры 'otherRect', в то время как переменная 'pictRect' больше нигде не участвует в вычислениях. Правильный код выглядит следующим образом:

bool IsFitRect(TPict& pict)
{
  TRect pictRect;
  ...
  pictRect = pict.GetRect();
  return pictRect.dx >= 16 && pictRect.dy >= 16;
}

Пример 2.

bool CreateMiniDump()
{
  BOOL bStatus = FALSE;
  CString errorMsg;
  ...
  if (hDbgHelp == NULL)
  {
    errorMsg = _T("dbghelp.dll couldn't be loaded");
    goto cleanup;
  }
  ...
  if (hFile == INVALID_HANDLE_VALUE)
  {
    errorMsg = _T("Couldn't create minidump file");
    return FALSE;
  }
  ...
cleanup:
  if (!bStatus)
    AddToReport(errorMsg);
  return bStatus;
}

В этом примере во всех блоках 'if' кроме одного после создания сообщения об ошибке выполняется переход в конец функции, где эта ошибка добавляется в отчёт. А при обработке одного из условий выполняется выход из функции сразу без добавления сообщения в отчёт, которое в итоге теряется. Корректный код выглядит следующим образом:

bool CreateMiniDump()
{
  BOOL bStatus = FALSE;
  CString errorMsg;
  ...
  if (hDbgHelp == NULL)
  {
    errorMsg = _T("dbghelp.dll couldn't be loaded");
    goto cleanup;
  }
  ...
  if (hFile == INVALID_HANDLE_VALUE)
  {
    errorMsg = _T("Couldn't create minidump file");
    goto cleanup;
  }
  ...
cleanup:
  if (!bStatus)
    AddToReport(errorMsg);
  return bStatus;
}

Иногда при работе с криптографическими функциями программисты очищают в конце переменные, записывая в них нулевое значение. Это неправильный подход, так компилятор скорее всего выбросит такой код при оптимизации, если переменная больше не используется. Например:

void ldns_sha256_update(...)
{
  size_t freespace, usedspace;
  ...
  /* Clean up: */
  usedspace = freespace = 0;
}

Для очистки памяти следует использовать специальные функции, которые не будут удалены компилятором во время оптимизации:

void ldns_sha256_update(...)
{
  size_t freespace, usedspace;
  ...
  /* Clean up: */
  RtlSecureZeroMemory(&usedspace, sizeof(usedspace));
  RtlSecureZeroMemory(&freespace, sizeof(freespace));
}

Подробнее об этой ошибке можно прочитать в описании диагностики V597.

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

static stbi_uc *stbi__tga_load(...)
{
  //   read in the TGA header stuff
  int tga_palette_start = stbi__get16le(s);
  int tga_palette_len = stbi__get16le(s);
  int tga_palette_bits = stbi__get8(s);
  ...
  //   the things I do to get rid of an error message,
  //   and yet keep Microsoft's C compilers happy... [8^(
  tga_palette_start = tga_palette_len = tga_palette_bits =
      tga_x_origin = tga_y_origin = 0;
  //   OK, done
  return tga_data;
}

Для таких случаев есть более красивые решения, например, можно использовать функцию:

template<class T> void UNREFERENCED_VAR( const T& ) { }
static stbi_uc *stbi__tga_load(...)
{
  //   read in the TGA header stuff
  int tga_palette_start = stbi__get16le(s);
  ...
  UNREFERENCED_VAR(tga_palette_start);
  ...
  //   OK, done
  return tga_data;
}

Или использовать специальные макросы, объявленные в системных заголовочных файлах. Например, в Visual C++ таким макросом является UNREFERENCED_PARAMETER. В этом случае анализатор также не будет выдавать предупреждения.

Данная диагностика классифицируется как:

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V1001.