Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
GBP
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Бесплатная лицензия PVS-Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
>
V668. Possible meaningless check for nu…
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Диагностика микро-оптимизаций (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Cтандарт MISRA
Стандарт AUTOSAR
Стандарт OWASP (C#)
Дополнительная информация
Оглавление

V668. Possible meaningless check for null, as memory was allocated using 'new' operator. Memory allocation will lead to an exception.

10 Май 2013

Анализатор обнаружил ситуацию, когда значение указателя возвращаемого оператором 'new' сравнивается с нулём. Как правило, это значит, что программа при невозможности выделить память будет вести себя не так, как ожидает программист.

Если оператор 'new' не смог выделить память, то согласно стандарту языка Си++, генерируется исключение std::bad_alloc(). Таким образом проверять указатель на равенство нулю не имеет смысла. Рассмотрим простейший случай:

MyStatus Foo()
{
  int *p = new int[100];
  if (!p)
    return ERROR_ALLOCATE;
  ...
  return OK;
}

Указатель 'p' никогда не будет равен нулю. Функция никогда не вернет константное значение ERROR_ALLOCATE. Если выделить память невозможно, то возникнет исключение. Исправим код наиболее простым образом:

MyStatus Foo()
{
  try
  { 
    int *p = new int[100];
    ...
  }
  catch(const std::bad_alloc &)
  {
    return ERROR_ALLOCATE;
  }
  return OK;
}

Отметим, что приведенный пример исправленного кода очень плох. Идеология работы с исключениями совсем иная. Исключения как раз позволяют избавиться от множества проверок и возвращаемых статусов. Лучше позволить исключению выйти за пределы функции 'Foo' и обработать его где-то на более высоком уровне. К сожалению, рассмотрение использования исключений выходит за рамки документации.

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

// For each processor; spawn a CPU thread to access details.
hThread = new HANDLE [nProcessors];
dwThreadID = new DWORD [nProcessors];
ThreadInfo = new PTHREADINFO [nProcessors];
// Check to see if the memory allocation happenned.
if ((hThread == NULL) ||
    (dwThreadID == NULL) ||
    (ThreadInfo == NULL))
{
  char * szMessage = new char [128];
  sprintf(szMessage,
          "Cannot allocate memory for "
          "threads and CPU information structures!");
  MessageBox(hDlg, szMessage, APP_TITLE, MB_OK|MB_ICONSTOP);
  delete szMessage;
  return false;
}

Пользователь никогда не увидит окошка с сообщением об ошибке. Если не удастся выделить память, программа аварийно завершится или выдаст неподходящее сообщение, обработав исключение в другом месте.

Частой причиной описанных проблем, является изменение в поведении оператора 'new'. Во времена Visual C++ 6.0, оператор 'new' в случае ошибки возвращал NULL. Следующие версии Visual C++ следуют стандарту и генерируют исключение. Помните про это изменение поведения. Таким образом, если вы адаптируете старый проект для сборки современным компилятором, вам стоит уделить повышенное внимание диагностике V668.

Примечание N1. Анализатор не будет выдавать предупреждение, если используется placement new или "new (std::nothrow) T". Пример такого кода:

T * p = new (std::nothrow) T; // OK
if (!p) {
  // An error has occurred.
  // No storage has been allocated and no object constructed.
  ...
}

Примечание N2. Есть возможность слинковать проект с nothrownew.obj. В этом случае, оператор new не будет генерировать исключение. Такой возможностью, например, пользуются разработчики драйверов. Подробнее: new and delete operators. В этом случае, просто отключите предупреждение V668.

Дополнительные материалы по данной теме:

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

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

Этот сайт использует куки и другие технологии, чтобы предоставить вам более персонализированный опыт. Продолжая просмотр страниц нашего веб-сайта, вы принимаете условия использования этих файлов. Если вы не хотите, чтобы ваши данные обрабатывались, пожалуйста, покиньте данный сайт. Подробнее →
Принять