V530. The return value of function 'Foo' is required to be utilized.


Вызов некоторых функций не имеет смысла, если результат их работы не используется. Рассмотрим первый пример:

void VariantValue::Clear()
{
  m_vtype = VT_NULL;
  m_bvalue = false;
  m_ivalue = 0;
  m_fvalue = 0;
  m_svalue.empty();
  m_tvalue = 0;
}

Этот код очистки значений взят из реального приложения. Ошибка заключается в том, что вместо функции string::clear() случайно вызывается функция string::empty() и содержимое строки остается неизменным. Ошибка диагностируется на основании того, что результат работы функции string::empty() обязательно должен быть использован. Например, результат должен быть с чем-то сравнен или записан в переменную.

Исправленный вариант кода:

void VariantValue::Clear()
{
  m_vtype = VT_NULL;
  m_bvalue = false;
  m_ivalue = 0;
  m_fvalue = 0;
  m_svalue.clear();
  m_tvalue = 0;
}

Второй пример:

void unregisterThread() {
  Guard<TaskQueue> g(_taskQueue);
  std::remove(_threads.begin(), _threads.end(),
              ThreadImpl::current());
}

Функция std::remove не удаляет элементы из контейнера. Она только сдвигает элементы и возвращает итератор на начало мусора. Пусть мы имеем контейнер vector<int>, содержащий элементы 1,2,3,1,2,3,1,2,3. Если выполнить код "remove( v.begin(), v.end(), 2 )", то контейнер будет содержать элементы 1,3,1,3,?,?,?, где ? - некий мусор. При этом функция вернет итератор на первый мусорный элемент, и если мы хотим удалить эти мусорные элементы, то должны написать код: "v.erase(remove(v.begin(), v.end(), 2), v.end())".

Как видно из объяснения, результат std::remove должен быть обязательно использован. Корректный код:

void unregisterThread() {
  Guard<TaskQueue> g(_taskQueue);
  auto trash = std::remove(_threads.begin(), _threads.end(),
                           ThreadImpl::current());
  _threads.erase(trash, _threads.end());
}

Функций, результат которых должен быть обязательно использован огромное количество. К ним можно отнести: malloc, realloc, fopen, isalpha, atof, strcmp и многие, многие другие функции. Неиспользуемый результат свидетельствует об ошибке, чаще всего связанный с допущенной опечаткой. Однако анализатор предупреждает только об ошибках связанных с использованием библиотеки STL. На это имеется две причины:

1) Допустить ошибку, не используя результат такой функции как fopen() намного сложней, чем спутать std::clear() и std::empty().

2) Данная функциональность будет дублировать возможности Code Analysis for C/C++, входящий в состав некоторых редакций Visual Studio (смотри предупреждение C6031). Однако в Visual Studio эти предупреждения не реализованы для функций STL.

Если вы хотите предложить расширить список функций, поддерживаемых анализатором, то обратитесь в поддержку. Мы будем благодарны за интересные примеры и советы.

Безопасность

Помимо явных ошибок и опечаток, следует рассмотреть тему безопасности. Существуют функции, связанные с разграничением доступа. В качества примера назовём только функции LogonUser и SetThreadToken, но на самом деле их много. Нужно обязательно проверять статусы, которые возвращают эти функции. Неиспользование значений, которые вернули эти функции, является грубой ошибкой и потенциальной уязвимостью. Именно поэтому для таких функций анализатор также выдает предупреждение V530.

Дополнительные возможности

Можно указать имена пользовательских функций, для которых следует выполнять проверку, используется ли возвращаемое функцией значение.

Возле прототипа функции (или в общем заголовочном файле) пишется комментарий специального вида. Пример использования:

//+V530, namespace:MyNamespace, class:MyClass, function:MyFunc
namespace MyNamespace {
  class MyClass {
    int MyFunc();
  }
  ....
  obj.MyFunc(); // warning V530
}

Формат:

  • Ключ function задает имя функции.
  • Ключ class задаёт имя класса, если функция определена в классе.
  • Ключ namespace задаёт имя пространства имён, если функция или метод класса определены в этом пространстве имён.

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

//V_RET_USE_ALL

Мы не рекомендуем использовать этот режим из-за выдачи очень большого количества предупреждений V530. Но если в вашем проекте это действительно необходимо, то вы можете воспользоваться этим специальным комментарием.

Согласно Common Weakness Enumeration, потенциальные ошибки, найденные с помощью этой диагностики, классифицируются как CWE-252.

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


А ты совершаешь ошибки в коде?

Проверь с помощью
PVS-Studio

Статический анализ
кода для C, C++ и C#

goto PVS-Studio;