Значение вне допустимой области 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Значение вне допустимой области



(баг частый, мелкий)

Пример 1.

int x, y, z;

// какой-то код

if  ((int p = x + y) < z)

  return 1;

Else

  return 0;

Если значение суммы x + y выходит за пределы диапазона значений типа int, возникает переполнение, и бит знака устанавливается в 1. Условие оказывается истинным, и вместо нуля возвращается единица.

Пример 2.

unsigned char a = 100; //01100100 двоичное

unsigned char   b = 200; //11001000

unsigned char  c = a + b; // 100101100 -> 00101100: переполнение

В итоге c = 100 + 200 будет равно 44.

Пример 3.

int a = 1000;

char b = a; /* переполнение при преобразовании int к char. В итоге b будет содержать лишь 8 младших битов a */

printf (“ b = %i\n”, b); // будет выведено b = -24

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

       double > float > int > char.

 Прилагательные long, long long, unsigned повышают ранг типа. Так что unsigned int > int. Если из небольшого значения а типа unsigned int вычесть какое – нибудь число, большее а, то отрицательный результат будет интерпретирован как очень большое положительное число. Такого рода ошибки часто возникают при работе с функциями, возвращающими тип size_t, например, length().

Пример.

/*Поиск вхождения строки “qwert” в строку   s. Функция возвращает позицию самого левого вхождения или -1 */

int find (char *s) {

for (int i =0; i < strlen(s) – 5; ++i)

  if (s[ i ] ==’q’ && s[i + 1] == ‘w’ && s[i + 2] == ‘e’ && s[i + 3] == ‘r’ && s[i + 4] == ‘t’)

                               return  i;

return -1;

}

Если длина строки s окажется меньше 5, то значение strlen(s) – 5 будет интерпретировано как огромное положительное число, что приведет к выходу за пределы строки и непредсказуемым последствиям.

Возможные верные варианты цикла:

for (int i =0; i < (int) strlen(s) – 5; ++i)

или

for (int i =0; i < (int)(strlen(s) – 5); ++i)

Можно предусмотреть случаи, когда s имеет длину < 5:

if (strlen(s) < 5) return -1;      

   

 

Переполнение буфера

(баг частый, катастрофический)

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

int main ()

{

   char ch [ 10 ];

    gets (ch); // может вызвать переполнение буфера

   ...

}

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

- «нападение на стек» - изменение адреса возврата с целью выполнения вредоносного кода

- перезапись указателя с целью получить определенные данные

- переполнение кучи.

 3. 4. Арифметические исключения

(баги частые, крупные / мелкие)

Арифметические исключения – класс ошибок. Некоторые примеры:

· Деление на 0

· Извлечение квадратного корня из отрицательного числа

· Исключения при работе с вещественными числами в формате с плавающей точкой

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

Пример. Вычисление площади треугольника по трем его сторонам (формула Герона).

#include < stdio.h >

#include < conio.h >

#include < math.h >

float   area (float   a, float   b, float c)

{

float   P = a + b + c;

float   p = P/2;

float   s = sqrt (p * (p – a) * (p – b) * (p – c));

return  s;

}

int main() {

  float test[4][3] = { { 3, 4, 5 }, { 5, 12, 13 }, { -3, -4, -5 }, { 3, 4, 8 } };

  for (int i = 0; i < 4; ++i)

          printf (“ area (%f, %f, %f) = %f\n”, test [ i ] [ 0 ], test [ i ] [ 1 ], test [ i ] [ 2 ],

                area (test [ i ] [ 0 ], test [ i ] [ 1 ], test [ i ] [ 2 ]))

getch ();

}

Вывод программы:

 area (3.000000, 4.000000, 5.000000) = 6.000000

area (5.000000, 12.000000, 13.000000) = 30.000000

area (-3.000000, -4.000000,-5.000000) = 6.000000

area (3.000000, 4.000000, 8.000000) = -1.#IND00

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

Решение в данном примере состоит в том, чтобы сделать защиту путем контроля вводимых данных: a > 0, b > 0, c > 0, a + b > c, a + c > b, b + c > a.

Off - by – one

(баг частый, крупный)

Это одна из наиболее общих ошибок. Примеры:

· Начальное значение переменной цикла for равно 1 вместо 0 или наоборот

· Написание <= N вместо < N или наоборот

· Цикл по элементам массива 1.. n вместо 0.. n-1

и т.д.

Приоритет операторов

(баг частый, мелкий)

Ошибку особенно трудно заметить напрямую. Чтобы избежать возникновения ошибки, достаточно знать правила приоритета операций языка программирования. Не следует писать длинных и сложных предложений. Имеет смысл использовать скобки для явного задания приоритетов, даже если они излишни (это к тому же облегчает чтение кода).

Пример: if ((x==0) && (y == 1))

                   z=1;

              else z=2;



Поделиться:


Последнее изменение этой страницы: 2021-03-09; просмотров: 68; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 13.58.252.8 (0.008 с.)