Overflow

Арифметическая операция вызывает переполнение

Описание

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

Результат проверки также зависит от заданного режима округления с плавающей точкой. По умолчанию режим округления to-nearest. См. Float rounding mode (-float-rounding-mode).

Нефинитные поплавки не разрешены

По умолчанию нефинитные поплавки не разрешены. Когда результат операции выходит за пределы допустимой области значений, происходит переполнение. Проверка:

  • Красный, если результат операции выходит за пределы допустимой области значений.

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

  • Зеленый, если результат операции не выходит за пределы допустимой области значений.

Чтобы точно настроить поведение проверки переполнения, используйте эти опции и задайте аргумент forbid, allow, или warn-with-wrap-around:

Типы данных операнда определяют допустимую область значений для арифметической операции. Если операция включает два операнда, верификация использует ANSI® Правила преобразования C для определения общего типа данных. Этот общий тип данных определяет допустимую область значений.

Для некоторых примеров правил преобразования смотрите Допущения о неявных преобразованиях типов данных.

Нефинитные поплавки разрешены

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

  • Красный, если операция создает бесконечность на всех путях выполнения, которые рассматривает программное обеспечение, и сами операнды не бесконечны.

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

  • Зеленый, если операция не производит бесконечность, если только сами операнды не бесконечны.

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

Чтобы включить этот режим верификации, используйте следующие опции:

Примеры

расширить все

void main() {
  int i=1;
  i = i << 30; //i = 2^30
  i = 2*i-2;
}

В этом примере операция 2*i приводит к значению 231. Проверка Overflow на умножение приводит к красной ошибке, поскольку максимальное значение, которое тип int может удерживать 32-битную цель равную 231-1.

void main(void)
 {
   int i;
   int shiftAmount = 1;

   i = 1090654225 << shiftAmount; 
 }

В этом примере происходит Overflow ошибка, сдвиг влево выполняется для целого числа со знаком.

#include <float.h>

void main() {
 float val = FLT_MAX;
 val = val * 2 + 1.0;
}

В этом примере FLT_MAX - максимальное значение, которое float может представлять на 32-битном целевом устройстве. Поэтому операция val * 2 приводит к Overflow ошибке.

void func(void) {
   float fVal = -2.0f;
   unsigned int iVal = (unsigned int)fVal; 
}

В этом примере проверка красного Overflow появляется на приведении от float на unsigned int. В соответствии со стандартом C99 (сноска к пункту 6.3.1.4) область значений значений, которые могут быть преобразованы из значений с плавающей точкой в беззнаковые целые числа при сохранении кода портативным, (-1, MAX + 1). Для значений с плавающей точкой за пределами этой области значений преобразование в беззнаковые целые числа не четко определено. Здесь, MAX - максимальное число, которое может храниться беззнаковым целым типом.

Даже если ошибка времени выполнения не возникает при выполнении кода на целевом объекте, приведение может оказаться неудачным для другого целевого объекта.

Коррекция - сначала приведение к целому числу со знаком

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

void func(void) {
   float fVal = -2.0f;
   int iValTemp = (int)fVal;
   unsigned int iVal = (unsigned int)iValTemp; 
}
#define FLT_MAX 3.40282347e+38F

void float_negative_overflow() {
   float min_float = -FLT_MAX;
   min_float = -min_float * min_float;
}

В float_negative_overflow, min_float содержит самое отрицательное число, которое имеет тип float может представлять. Потому что операция -min_float * min_float задает число, которое более отрицательно, чем это число, тип float не может представлять его. Проверка Overflow приводит к красной ошибке.

#include <stdio.h>

struct
{
  unsigned int dayOfWeek : 2;
} Week;

void main()
{
  unsigned int two = 2, three = 3, four = 4;
  Week.dayOfWeek = two;
  Week.dayOfWeek = three;
  Week.dayOfWeek = four;
}

В этом примере dayOfWeek занимает 2 бита. Это может иметь значения в [0,3] потому что это беззнаковое целое число. Когда вы присваиваете значение 4 dayOfWeekпроверка Overflow красная.

Чтобы обнаружить переполнения целых и беззнаковых целых чисел, на панели Configuration, в разделе Check Behavior, выберите forbid или warn-with-wrap-around для Overflow mode for signed integer и Overflow mode for unsigned integer.

Результаты в forbid режим:

double func(void) {
    double x=1.0/0.0;
    return x;
}
В этом примере оба операнда / операция не бесконечна, но результатом является бесконечность. Проверка Overflow на - операция красная. В forbid режим остановки верификации после проверки красным цветом. Например, проверка Non-initialized local variable не отображается на x в return оператор. Если вы не включаете опции Allow non finite floats, появляется проверка Division by zero, поскольку бесконечность не разрешена.

Результаты в warn-first режим:

double func(void) {
    double x=1.0/0.0;
    return x;
}
В этом примере оба операнда / операция не бесконечна, но результатом является бесконечность. Проверка Overflow на - операция красная. Красный заселяется warn-first режим отличается от красных проверок для других типов проверок. После красной проверки верификации не останавливается. Например, зеленая проверка Non-initialized local variable появится на x в return оператор. В результате верификации, если вы поместите курсор на xВы видите, что это имеет значение Inf.

Результаты в forbid режим:

void func(double arg1, double arg2) {
    double ratio1=arg1/arg2;
    double ratio2=arg1/arg2;
}
В этом примере значения arg1 и arg2 неизвестны для верификации. Эта верификация принимает, что arg1 и arg2 может иметь все возможные double значения. Для образца, arg1 может быть ненулевым и arg2 может быть нулем и результатом ratio1=arg1/arg2 может быть бесконечностью. Поэтому в операции деления появляется оранжевая проверка Overflow. После проверки верификация завершает поток выполнения, который приводит к бесконечности. Эта верификация принимает, что arg2 не может быть нулем после оранжевого чека. Проверка Overflow на операцию второго деления ratio2=arg1/arg2 зеленый.

Результаты в warn-first режим:

void func(double arg1, double arg2) {
    double ratio1=arg1/arg2;
    double ratio2=arg1/arg2;
}
В этом примере значения arg1 и arg2 неизвестны для верификации. Эта верификация принимает, что arg1 и arg2 может иметь все возможные double значения. Для образца, arg1 может быть ненулевым и arg2 может быть нулем и результатом ratio1=arg1/arg2 может быть бесконечностью. На операции деления появляется оранжевая проверка Overflow. Оранжевый сдает warn-first режим отличается от оранжевых проверок для других типов проверок. После проверки верификация не завершает поток выполнения, который приводит к бесконечности. Эта верификация сохраняет нулевое значение arg2 после оранжевой проверки. Поэтому Overflow проверяйте на второй операции деления ratio2=arg1/arg2 также оранжевый.

Проверяйте информацию

Группа: Численный
Язык: C | C++
Акроним: ОВФЛ