Анализатор обнаружил потенциально возможную ошибку, связанную с тем, что перед выходом из функции в локальную переменную присваивается значение, которое потом нигде не используется.
Возможно, эта переменная должна участвовать в последующих операциях или возращена как результат функции, но из-за опечатки используется другая переменная, или программист забыл написать соответствующий код. Рассмотрим примеры.
Пример 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. |