# 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. В этом случае анализатор также не будет выдавать предупреждения.

Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки некорректного использования системных процедур и интерфейсов, связанных с обеспечением информационной безопасности (шифрования, разграничения доступа и пр.).

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

CWE-14 CWE-563 CERT-MSC06-C CERT-MSC13-C

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