Предупреждение с26451 как исправить

Арифметическое переполнение C++ Решение и ответ на вопрос 2576074

Battary

7 / 6 / 1

Регистрация: 29.10.2016

Сообщений: 175

1

Арифметическое переполнение

27.01.2020, 18:33. Показов 27493. Ответов 4

Метки нет (Все метки)


Доброго всем времени суток!

Никак не могу решить проблему с этим:

Кликните здесь для просмотра всего текста

C26451 Арифметическое переполнение: использование оператора «-» на байтовом значении 4 и приведение результата к байтовому значению 8. Приведите значение к более широкому типу перед вызовом оператора «-«, чтобы избежать переполнения (io.2).
Строки: 9 14 15 16 17 18 19;
Выражение: j+1

Собственно почему? Я же прибавляю 4байтовый int (1) к 4байтовому j.
Я в курсе, что возвращаемое значение метода .size() не int, а size_t, но ни замена int на size_t в for, ни приведение к int не решают эту проблему. Как можно решать это?

Функция

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
template <typename T>
int SortVector(vector<Box<T>>& alph)//Сортировка по возрастанию
{
    WhiteBox<T> temp;
    for (int i = 0; i < alph.size() - 1; i++)
    {
        for (int j = 0; j < alph.size() - i - 1; j++)
        {
            if (alph[j].Get_maxLimit() > alph[j + 1].Get_maxLimit()) 
            {
                temp.Set_maxLimit(alph[j].Get_maxLimit());
                temp.Set_minLimit(alph[j].Get_minLimit());
                temp.Set_symbol(alph[j].Get_symbol());
                alph[j].Set_maxLimit(alph[j + 1].Get_maxLimit());
                alph[j].Set_minLimit(alph[j + 1].Get_minLimit());
                alph[j].Set_symbol(alph[j + 1].Get_symbol());
                alph[j + 1].Set_maxLimit(temp.Get_maxLimit());
                alph[j + 1].Set_minLimit(temp.Get_minLimit());
                alph[j + 1].Set_symbol(temp.Get_symbol());
            }
        }
    }
    return 0;
}

Класс

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename T>
class Box
{
protected:
    T minLimit = numeric_limits<T>::min();                              //Нижняя граница отрезка
    T maxLimit = numeric_limits<T>::min();                              //Верхняя граница отрезка
 
public:
    Box() {};
    Box(T min, T max)
    {
        minLimit = min;
        maxLimit = max;
    };
 
    //Set-functions
    void Set_minLimit(T value) { minLimit = value; }
    void Set_maxLimit(T value) { maxLimit = value; }
 
    //Get-functions
    T Get_minLimit() { return minLimit; };
    T Get_maxLimit() { return maxLimit; };
};

Main

C++
1
2
3
4
5
6
7
8
//Зависимости опущены
int main()
{
vector<Box<uint32_t>> alphabet;
//Тут мог быть ввод с клавиатуры
SortVector(alphabet);
return 0;
}

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

27.01.2020, 18:33

Ответы с готовыми решениями:

Переполнение
При вводе слишком большого числа (например: 4444444444444444) программа зацикливается и постоянно…

Переполнение
Доброго времени суток! Есть код:

void menu()
{
IndexList Universal;
List *tmp = NULL;
int…

Переполнение
При выводе числа происходит переполнение и пребовление числа 64. Подскажите почему прибавилось…

Exception переполнение
Подскажите пожалуйста, вот есть для встроенная библиотека для обработки ошибко exception.
В ней…

4

6574 / 4559 / 1843

Регистрация: 07.05.2019

Сообщений: 13,726

27.01.2020, 19:08

2

Цитата
Сообщение от Battary
Посмотреть сообщение

Я в курсе, что возвращаемое значение метода .size() не int, а size_t, но ни замена int на size_t в for, ни приведение к int не решают эту проблему. Как можно решать это?

Используй size_t в обоих циклах, для i и для j. Зачем тебе там int?



0



7 / 6 / 1

Регистрация: 29.10.2016

Сообщений: 175

27.01.2020, 20:07

 [ТС]

3

Цитата
Сообщение от oleg-m1973
Посмотреть сообщение

Используй size_t в обоих циклах, для i и для j. Зачем тебе там int?

Я пробовал, ошибка не уходит. А int там нужен, потому что массив не больше 1000.



0



6574 / 4559 / 1843

Регистрация: 07.05.2019

Сообщений: 13,726

27.01.2020, 21:10

4

Лучший ответ Сообщение было отмечено Battary как решение

Решение

Цитата
Сообщение от Battary
Посмотреть сообщение

Я пробовал, ошибка не уходит. А int там нужен, потому что массив не больше 1000.

Во-первых, это не ошибка, а предупреждение, в принципе можно забить.
Во-вторых, int там не нужен, это не от размера зависит.
В-третьих, попробуй привести единицу к size_t: i < alph.size() — size_t(1);



0



большой ДЕН

1 / 1 / 0

Регистрация: 01.05.2017

Сообщений: 144

26.09.2020, 19:15

5

Привет.
Есть такая функция

C++
1
2
3
4
5
template<typename T>
    inline double lef1(T b, int k) {
 
        return (0.75 + 0.25 * pow(static_cast<double> (b) / (k - 1), 2 * k - 3)) / 0.5;
    }

Выражение «(k — 1)» подчеркнутос предупреждением «c26451 арифметическое переполнение использование оператора «-» на байтовом значении 4 и приведение результата к байтовому значению 8″
Я совсем не понимаю почему так. Подскажите, пожалуйста, как правильно должно быть



0



IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

26.09.2020, 19:15

Помогаю со студенческими работами здесь

Задача на переполнение
Вот такая задачка: Дано число в двоичном виде состоящее из 1млн (короче из огромного количества)…

Переполнение стека
Хочу полюбопытствовать. Вычитал недавно, что на стек выделяется ограниченная область памяти, и в…

Переполнение double
Здравствуйте!

как отловить переполнение при расчетах double;

double db =…

Переполнение буфера
Добрый день! В общем:
#include &quot;stdafx.h&quot;
#include &lt;iostream&gt;
using namespace std;

int…

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:

5

In C++ (and pretty much any other C-like high level languages) arithmetic operations between 2 numbers produces a value of the same type if the original types are the same, and a value of the common type of the two if they’re different. Indeed multiplying two 32-bit numbers produces a 64-bit result but that’s not how C++ works

The arguments of the following arithmetic operators undergo implicit conversions for the purpose of obtaining the common real type, which is the type in which the calculation is performed:

  • binary arithmetic *, /, %, +, —
  • relational operators <, >, <=, >=, ==, !=
  • binary bitwise arithmetic &, ^, |,
  • the conditional operator ?:

https://en.cppreference.com/w/c/language/conversion

The full rule to obtain the common type can be read in the link above, or in the standard below

If m and n are ints then their product is also an int. Hence there’s a warning in new int[m * n]; because the new operator receives a size_t which is a 64-bit unsigned type on your platform. Same to new int[(long)m * n] because the common type of long and int is long (which is also a 32-bit type on Windows)

To get the full 64-bit product you need to cast at least one of the operands to a 64-bit type which is long long in MSVC. That’s why the last line new int[(long long)m * n]; works. However you’ll get a warning related to conversion between signed and unsigned

From ISO/IEC 9899:201x C++ standard

6.3.1.8 Usual arithmetic conversions

Many operators that expect operands of arithmetic type cause conversions and yield result types in a similar way. The purpose is to determine a common real type for the operands and result. For the specified operands, each operand is converted, without change of type domain, to a type whose corresponding real type is the common real type. Unless explicitly stated otherwise, the common real type is also the corresponding real type of the result, whose type domain is the type domain of the operands if they are the same, and complex otherwise. This pattern is called the usual arithmetic conversions:

  • First, if the corresponding real type of either operand is long double, the other operand is converted, without change of type domain, to a type whose
    corresponding real type is long double.
  • Otherwise, if the corresponding real type of either operand is double, the other operand is converted, without change of type domain, to a type whose
    corresponding real type is double.
  • Otherwise, if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose
    corresponding real type is float.
  • Otherwise, the integer promotions are performed on both operands. Then the
    following rules are applied to the promoted operands:

    • If both operands have the same type, then no further conversion is needed.
      Otherwise, if both operands have signed integer types or both have unsigned
      integer types, the operand with the type of lesser integer conversion rank is
      converted to the type of the operand with greater rank.
      Otherwise, if the operand that has unsigned integer type has rank greater or
      equal to the rank of the type of the other operand, then the operand with
      signed integer type is converted to the type of the operand with unsigned
      integer type.
    • Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the
      operand with signed integer type.
    • Otherwise, both operands are converted to the unsigned integer type
      corresponding to the type of the operand with signed integer type.

In C++ (and pretty much any other C-like high level languages) arithmetic operations between 2 numbers produces a value of the same type if the original types are the same, and a value of the common type of the two if they’re different. Indeed multiplying two 32-bit numbers produces a 64-bit result but that’s not how C++ works

The arguments of the following arithmetic operators undergo implicit conversions for the purpose of obtaining the common real type, which is the type in which the calculation is performed:

  • binary arithmetic *, /, %, +, —
  • relational operators <, >, <=, >=, ==, !=
  • binary bitwise arithmetic &, ^, |,
  • the conditional operator ?:

https://en.cppreference.com/w/c/language/conversion

The full rule to obtain the common type can be read in the link above, or in the standard below

If m and n are ints then their product is also an int. Hence there’s a warning in new int[m * n]; because the new operator receives a size_t which is a 64-bit unsigned type on your platform. Same to new int[(long)m * n] because the common type of long and int is long (which is also a 32-bit type on Windows)

To get the full 64-bit product you need to cast at least one of the operands to a 64-bit type which is long long in MSVC. That’s why the last line new int[(long long)m * n]; works. However you’ll get a warning related to conversion between signed and unsigned

From ISO/IEC 9899:201x C++ standard

6.3.1.8 Usual arithmetic conversions

Many operators that expect operands of arithmetic type cause conversions and yield result types in a similar way. The purpose is to determine a common real type for the operands and result. For the specified operands, each operand is converted, without change of type domain, to a type whose corresponding real type is the common real type. Unless explicitly stated otherwise, the common real type is also the corresponding real type of the result, whose type domain is the type domain of the operands if they are the same, and complex otherwise. This pattern is called the usual arithmetic conversions:

  • First, if the corresponding real type of either operand is long double, the other operand is converted, without change of type domain, to a type whose
    corresponding real type is long double.
  • Otherwise, if the corresponding real type of either operand is double, the other operand is converted, without change of type domain, to a type whose
    corresponding real type is double.
  • Otherwise, if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose
    corresponding real type is float.
  • Otherwise, the integer promotions are performed on both operands. Then the
    following rules are applied to the promoted operands:

    • If both operands have the same type, then no further conversion is needed.
      Otherwise, if both operands have signed integer types or both have unsigned
      integer types, the operand with the type of lesser integer conversion rank is
      converted to the type of the operand with greater rank.
      Otherwise, if the operand that has unsigned integer type has rank greater or
      equal to the rank of the type of the other operand, then the operand with
      signed integer type is converted to the type of the operand with unsigned
      integer type.
    • Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the
      operand with signed integer type.
    • Otherwise, both operands are converted to the unsigned integer type
      corresponding to the type of the operand with signed integer type.

Как устранить эти предупреждения?

// midiNote is a double as it is used in floating point equation
// v is int because that's informative that the function wants whole numbers
void setMidiNote(int v) { midiNote = v-48;  }

Предупреждение C26451 Арифметическое переполнение: использование оператора ‘-‘ для 4-байтового значения и последующее приведение результата к 8-байтовому значению. Перед вызовом оператора ‘-‘ приведите значение к более широкому типу, чтобы избежать переполнения (io.2).

// input should be 0 to 10 integer, and dank will be odd integers only
// dank is a double, it is ultimately used in a floating point equation
void setDarkIntensity(int v) { dank = v * 2 + 1; }

Предупреждение C26451 Арифметическое переполнение: использование оператора ‘*’ для 4-байтового значения и последующее преобразование результата к 8-байтовому значению. Перед вызовом оператора ‘*’ приведите значение к более широкому типу, чтобы избежать переполнения (io.2).

Предупреждение C26451 Арифметическое переполнение: использование оператора ‘+’ для 4-байтового значения и последующее приведение результата к 8-байтовому значению. Приведите значение к более широкому типу перед вызовом оператора ‘+’, чтобы избежать переполнения (io.2).

7 ответов

Предупреждения говорят вам, что существует вероятность того, что ваши вычисления переполнят исходный (меньший) тип перед преобразованием в результат (больший) тип. В первом случае, если v равно MIN_INT (-2 31 ), вычитание опустится, что приведет к неопределенному поведению (вероятно, большое положительное число), которое затем будет сохранено в midiNote. Чтобы избежать предупреждения, сначала конвертируйте в более крупный тип:

midiNote = double(v) - 48;

Аналогично вашему второму примеру.

Хотя вы можете знать, что setMidiNote не будет вызываться со значениями, которые будут иметь эту проблему, компилятор не знает и выдает это предупреждение, чтобы предупредить вас о возможности возникновения проблемы.


7

1201ProgramAlarm
5 Май 2019 в 22:58

Я считаю, что это ошибка VS2019. Он больше не отмечен в VS2022.

Например, это вызывает предупреждение

double test2(int n)
{
     return 4.0 * (n - 1);
}

Но это не так

int test2a(int n)
{
    return 4 * (n - 1);
}

Однако для последнего риск неопределенного поведения намного выше. Умножение на 4 значительно увеличивает риск UB, поскольку очень большой набор n даст UB. Как здорово? Что ж, есть только одно возможное значение n из примерно 4 миллиардов возможных значений в первом примере, которое переполняется. Во втором есть около 3 миллиардов n, которые могут быть переполнены / не заполнены. Почему? Потому что целочисленная арифметика была бы невозможна, если бы каждое выражение с большей сложностью, чем добавление 0 или умножение на 1, было помечено, потому что оно могло переполняться.

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

Этот ответ показывает способ отключить это предупреждение в VS 2019 в редакторе набора правил анализа кода.

Предупреждение C26454: арифметическое переполнение: операция ‘-‘ дает отрицательный результат без знака во время компиляции (io.5)

Однако Microsoft, начиная с VS2022, больше не выдает предупреждение C26451 в виде волнистой линии для этого. И не отображается под -Wall. Видимо, они увидели свет.


19

doug
15 Дек 2021 в 06:56

Я решил проблему, посмотрев на Microsoft Docs, но вы также можете изменить свой переменная в тип long long (я знаю, сверху). Это избавило меня от ошибок. Надеюсь, они скоро займутся этим.


3

KoalaZub
2 Янв 2020 в 16:30

Я избавился от предупреждения, изменив тип переменной на «unsigned __int64». Это то, что предлагает сообщество разработчиков Microsoft!


3

passionateProgrammer
2 Май 2020 в 19:57

Static_cast<>() является рекомендуемым решением. В книге, которую я сейчас читаю, большое внимание уделяется этому новому соглашению о приведении типов. Простое использование (v) считается стилем C.. (Согласно литературе). .Интересно.. сработает ли просто объявить v как auto. Похоже, Вектор что-то замышляет…

Недействительным setDarkIntensity (авто v) { сырой = v * 2 + 1; }


0

George Abraham
3 Авг 2022 в 20:03

Приведите тип данных, который вы хотите, как можно раньше, а затем используйте его полностью:

// midiNote is a double as it is used in floating point equation
// v is int because that's informative that the function wants whole numbers
void setMidiNote(int v) { midiNote = static_cast<double>(v) - 48.0;  }
// input should be 0 to 10 integer, and dank will be odd integers only
// dank is a double, it is ultimately used in a floating point equation
void setDarkIntensity(int v) { dank = static_cast<double>(v) * 2.0 + 1.0; }

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

Использование 2.0 вместо 2 приводит к неявному приведению v к double, но явное приведение всегда более понятно.

Дополнительный совет: рассмотрите возможность проверки любых предположений в отладочных сборках. Это поможет избежать нарушения этих предположений при изменении кода в будущем. Что-то типа:

// input should be 0 to 10 integer, and dank will be odd integers only
// dank is a double, it is ultimately used in a floating point equation
void setDarkIntensity(int v) 
{ 
    assert(v >= 0 && v <= 10);
    dank = static_cast<double>(v) * 2.0 + 1.0; 
}

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


0

Darrin Cullop
5 Авг 2022 в 20:00

title description ms.date f1_keywords helpviewer_keywords

Warning C26451

Describes the causes of MSVC code analysis warning C26451, and shows how to fix it.

07/15/2020

C26451

RESULT_OF_ARITHMETIC_OPERATION_CAST_TO_LARGER_SIZE

C26451

Warning C26451

Arithmetic overflow: Using operator ‘operator‘ on a size-a byte value and then casting the result to a size-b byte value. Cast the value to the wider type before calling operator ‘operator‘ to avoid overflow (io.2)

This warning indicates incorrect behavior that results from integral promotion rules and types larger than the ones in which arithmetic is typically performed.

Remarks

Code analysis detects when an integral value gets shifted left, multiplied, added, or subtracted, and the result gets cast to a wider integral type. If the operation overflows the narrower integral type, then data is lost. You can prevent this loss by casting the value to a wider type before the arithmetic operation.

Code analysis name: RESULT_OF_ARITHMETIC_OPERATION_CAST_TO_LARGER_SIZE

Example 1

The following code generates this warning:

void leftshift(int i) noexcept
{
  unsigned __int64 x;
  x = i << 31;  // C26451 reported here

  // code
}

To correct this warning, use the following code:

void leftshift(int i) noexcept
{
  unsigned __int64 x;
  x = static_cast<unsigned __int64>(i) << 31; // OK

  // code
}

Example 2

void somefunc(__int64 /* y */) noexcept
{}

void callsomefunc(int x) noexcept
{
  somefunc(x * 2); // C26451 reported here
}

To correct this warning, use the following code:

void callsomefunc(int x) noexcept
{
  somefunc(static_cast<__int64>(x) * 2); // OK
}

Example 3

__int64 add(int x) noexcept
{
  constexpr auto value = 2;
  return x += value; // C26451 reported here
}

To correct this warning, use the following code:

__int64 add(int x) noexcept
{
  constexpr auto value = 2;
  const __int64 y = static_cast<__int64>(x) + value; // OK
  return y;
}

See also

  • ES.103: Don’t overflow
title description ms.date f1_keywords helpviewer_keywords

Warning C26451

Describes the causes of MSVC code analysis warning C26451, and shows how to fix it.

07/15/2020

C26451

RESULT_OF_ARITHMETIC_OPERATION_CAST_TO_LARGER_SIZE

C26451

Warning C26451

Arithmetic overflow: Using operator ‘operator‘ on a size-a byte value and then casting the result to a size-b byte value. Cast the value to the wider type before calling operator ‘operator‘ to avoid overflow (io.2)

This warning indicates incorrect behavior that results from integral promotion rules and types larger than the ones in which arithmetic is typically performed.

Remarks

Code analysis detects when an integral value gets shifted left, multiplied, added, or subtracted, and the result gets cast to a wider integral type. If the operation overflows the narrower integral type, then data is lost. You can prevent this loss by casting the value to a wider type before the arithmetic operation.

Code analysis name: RESULT_OF_ARITHMETIC_OPERATION_CAST_TO_LARGER_SIZE

Example 1

The following code generates this warning:

void leftshift(int i) noexcept
{
  unsigned __int64 x;
  x = i << 31;  // C26451 reported here

  // code
}

To correct this warning, use the following code:

void leftshift(int i) noexcept
{
  unsigned __int64 x;
  x = static_cast<unsigned __int64>(i) << 31; // OK

  // code
}

Example 2

void somefunc(__int64 /* y */) noexcept
{}

void callsomefunc(int x) noexcept
{
  somefunc(x * 2); // C26451 reported here
}

To correct this warning, use the following code:

void callsomefunc(int x) noexcept
{
  somefunc(static_cast<__int64>(x) * 2); // OK
}

Example 3

__int64 add(int x) noexcept
{
  constexpr auto value = 2;
  return x += value; // C26451 reported here
}

To correct this warning, use the following code:

__int64 add(int x) noexcept
{
  constexpr auto value = 2;
  const __int64 y = static_cast<__int64>(x) + value; // OK
  return y;
}

See also

  • ES.103: Don’t overflow

Понравилась статья? Поделить с друзьями:
  • Предупреждение при загрузке файлов произошла ошибка радмир
  • Предупреждение грамматических ошибок на синтаксическом уровне методика работы над ними
  • Предупреждение грамматических ошибок на морфологическом уровне
  • Предупреждение вероятная угроза безопасности как исправить
  • Предупреждение unable to access an error message corresponding to your field name