Предупреждение C26430
Символ не проверяется на значение NULL во всех путях.
Основные рекомендации по C++ : F.23: используйте not_null<T>, чтобы указать, что значение NULL не является допустимым значением
Если код когда-либо проверяет переменные указателя на значение NULL, он должен сделать это согласованно и проверить указатели на всех путях. Иногда перегрессивная проверка на значение NULL по-прежнему лучше, чем вероятность жесткого сбоя в одной из сложных ветвей. В идеале такой код следует рефакторинговать, чтобы быть менее сложным (путем разделения его на несколько функций) и полагаться на маркеры, такие как gsl::not_null
. Эти маркеры позволяют коду изолировать части алгоритма, которые могут делать безопасные предположения о допустимых значениях указателя. Правило TEST_ON_ALL_PATHS
помогает найти места, где проверки null несогласованы (это означает, что предположения могут потребовать проверки). Кроме того, он находит фактические ошибки, в которых потенциальное значение NULL может обойти проверки NULL в некоторых путях кода.
Замечания
Это правило предполагает, что код разыменовывает переменную указателя, чтобы проверка null (или применение значения, отличного от NULL), была оправдана. Если разыменовки нет, правило приостановлено.
Текущая реализация обрабатывает только простые указатели (или их псевдонимы) и не обнаруживает смарт-указатели, хотя проверки NULL применимы и к смарт-указателям.
Переменная помечается как проверяемая значение NULL, если она используется в следующих контекстах:
- как выражение символа в условии ветви, например в
if (p) { ... }
; - в небитовых логических операциях;
- в операциях сравнения, где один операнд является константным выражением, которое оценивается как нулевое.
Неявные проверки null предполагаются при назначении значения указателя:
- выделение, выполняемое с помощью бросания
operator new
; - указатель, полученный из типа, помеченного как
gsl::not_null
.
Пример
несогласованное тестирование показывает ошибку логики
void merge_states(const state *left, const state *right) // C26430
{
if (*left && *right)
converge(left, right);
else
{
// ...
if (!left && !right) // Logic error!
discard(left, right);
}
}
несогласованное тестирование показывает ошибку логики — исправлена
void merge_states(gsl::not_null<const state *> left, gsl::not_null<const state *> right)
{
if (*left && *right)
converge(left, right);
else
{
// ...
if (*left && *right)
discard(left, right);
}
}
Эвристика
При обеспечении того, что разыменовка указателя не имеет значения NULL, это правило не требует , чтобы каждое разыменовывание было предварительно проверено на значение NULL. Вместо этого он требует проверки null перед первым разыменовкой указателя. Следующая функция не активирует C26430:
void f(int* p)
{
if (p)
*p = 1;
*p = 2;
}
Следующая функция создает C26430, так как существует путь для назначения *p
без проверки null:
void f(bool b, int* p)
{
if (b && p)
*p = 1;
*p = 2;
}
Правила C26822 и C26823 применяются к расшифровке указателя null (возможно).
Это правило не выполняет полное отслеживание потока данных. Он может привести к неправильным результатам в случаях, когда используются косвенные проверки, например, когда промежуточная переменная содержит значение NULL и позже используется в сравнении.