Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

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

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

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

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

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

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


Если вы так и не получили ответ, пожалуйста, проверьте, отфильтровано ли письмо в одну из следующих стандартных папок:

  • Промоакции
  • Оповещения
  • Спам

Вебинар: Парсим С++ - 25.10

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

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.