Наименьшее отрицательное значение знакового целочисленного типа не имеет соответствующей положительной величины. В результате вычисления модуля числа от такого значения функциями 'abs', 'labs', 'llabs' возникает переполнение. Это приводит к неопределённому поведению.
Рассмотрим пример:
#include <iostream>
#include <cmath>
#include <limits.h>
int main()
{
int min = INT_MIN;
// error: abs(-2147483648) = -2147483648
std::cout << "abs(" << min << ") = "
<< abs(min); // <=
return 0;
}
Минимальное значение 32-битного знакового типа 'int' имеет значение 'INT_MIN', равное -2147483648. При этом максимальное значение 'INT_MAX' равно 2147483647, что на единицу меньше, чем настоящий модуль числа 'INT_MIN'. В данном случае в результате вычисления модуля получилось отрицательное число, равное исходному значению аргумента. Это может привести к ошибке в пограничном случае, когда код не рассчитан на обработку отрицательных чисел, полученных после вычисления модуля числа.
Для остальных значений функция вычисления модуля будет вести себя ожидаемым образом:
int main()
{
int notQuiteMin = INT_MIN + 1;
// ok: abs(-2147483647) = 2147483647
std::cout << "abs(" << notQuiteMin << ") = "
<< abs(notQuiteMin);
return 0;
}
Возможно, перед расчётом модуля стоит сделать специальную проверку значения аргумента, чтобы не допустить возникновения пограничного случая:
void safe_abs_call(int value)
{
if (value == INT_MIN)
return;
std::cout << "abs(" << value << ") = " << abs(value);
}
Срабатывание диагностики можно подавить в случаях, если де-факто диапазон передаваемых функциям 'abs', 'labs' и 'llabs' значений не может достигать минимальной величины.
Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки целочисленного переполнения и некорректного совместного использования знаковых и беззнаковых чисел. |
Данная диагностика классифицируется как:
|