Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Функция возвращает локальные переменные
(баг редкий, катастрофический) Переменные, объявленные в теле функции, хранят некоторые локальные данные. Если данные выделены динамически, они находятся в куче. Если же переменные объявлены статически, они будут сохранены в стеке. Если функция запрограммирована так, что она возвращает адрес локальной переменной, то программа, которая обратится по этому адресу, получит доступ к стеку. int foo () { int ch; do { ch = getch (); } while (ch < ‘0’ || ch > ‘9’); //вводим цифру return &ch; } Функция возвращает адрес локальной переменной, которая находится в стеке. Но самой переменной уже нет, после возврата из функции часть стека, занятая ее данными, была освобождена и будет отдана другим функциям. В результате после попытки использовать для чтения или для записи адрес, который вернула функция, возникает ошибка. Освобождение уже освобожденных ресурсов. (баг частый, крупный) Программист пытается освободить память, которая уже освобождена. В общем случае ресурсы сначала выделяются, а затем освобождаются. При повторном освобождении может возникнуть зацикливание. void swap (int *x, int *y) { //крайне неэффективная реализация функции обмена двух int int *tmp; tmp = (int *) malloc (sizeof (int)); if (*x == *y) free (tmp); *tmp = *x; *x = *y; *y = *tmp; free (tmp); } int main () { int a, b; a = 3; b = 4; swap (&a, &b); // ошибки нет a = 5; b = 5; swap (&a, &b); // ошибка } Разыменование NULL (баг частый, катастрофический) К этому багу ведет некорректная инициализация или ее отсутствие. Чтобы разыменовать область памяти, нужно ее до этого выделить. float *arr; int n; printf (“ n = “); scanf (“%i”, &n); if (n > 0) arr = (float *) malloc (n * sizeof (float)); *arr = 1.0; // если n <= 0, то возникнет ошибка Также данная ошибка может возникнуть из-за использования псевдонимов (две переменные ссылаются на один и тот же объект; после того, как память освобождена через одну переменную, делается попытка использовать другую переменную). int *ptr1; int *ptr2; ptr1 = (int *) malloc (sizeof (int)); ptr2 = ptr1; ... free (ptr1); *ptr2 = 666; Псевдонимы (алиасы, aliases) Использование программистом большого количества псевдонимов для одной и той же переменой может привести к появлению ошибок. Передача функции фактических параметров по ссылке (баг частый, крупный) Некоторой функции передаются две ссылки одного и того же типа. Функция изменяет данные, которые находятся по первой ссылке, используя данные, полученные по второй ссылке. Если обе ссылки совпадают, возникает ошибка
Пример 1. char *src; // какой-то код char *destn = src; strcat (src, destn); /* если фактические параметры src и destn псевдонимы, то возникает баг*/
Пример 2. #include < stdio.h > #include < conio.h > void sum (int &a, int &b, int &c) { // очень медленная, но работающая функция сложения двух чисел с = 0; for (int i = 0; i < a; ++i) c++; for (int i = 0; i < b; ++i) c++; } int main () { int aa, bb, cc; aa = 3; bb = 4; // правильный вариант printf (“ aa = %i \n bb = %i \n”, aa, bb); sum (aa, bb, cc); printf (“ aa + bb = %i\n”, cc); // неправильный вариант printf (“ aa = %i \n bb = %i \n”, aa, bb); sum (aa, bb, aa); printf (“ aa + bb = %i\n”, aa); getch (); return 0; } Во втором случае использования функции sum (aa, bb, aa) переменная aa обнулится сразу в начале функции sum. Затем произойдет инициализация первого цикла int i = 0, проверка условия цикла i < a вернет false, и первый цикл не выполнится ни разу. Во втором цикле значение переменной aa увеличится bb раз на 1 и станет равным bb. В итоге на экран будет выдано aa = 3 bb = 4 aa + bb = 7 aa = 3 bb = 4 aa + bb = 4 Ошибки данных. Арифметические ошибки Неинициализированная память (баг редкий, крупный) Пример 1. Поиск максимума в массиве. int imax, max, arr [ 10 ]; ... max = arr[0]; for (int i = 1; i < 10; ++i) if (arr [ i ] > max) { max = arr [ i ]; imax = i; } printf (“ max = a [ %i ] = %i\n”, imax, max); Если максимальным является элемент arr [ 0 ], то переменная imax останется неинициализированной, и на экране вполне может появиться что-нибудь вроде max = arr [ -13267 ] = 11 Пример 2. Для инициализации переменной может быть использован оператор switch. Но некоторые случаи могут быть пропущены из-за того, что соответствующие пути выполнения не были предусмотрены. int x; switch (getch ()) { case ‘0’: x = 0; break; case ‘1’: x = 1; break; } return x; Простейшее решение проблемы – использовать объявление с инициализацией: int x = -1; и проверять возвращенное функцией значение { 0, 1, -1 }. Более сложная, но лучшая стратегия – рассмотреть все возможные сценарии и пути выполнения в операторе switch.
|
||||||
Последнее изменение этой страницы: 2021-03-09; просмотров: 71; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.135.194.251 (0.013 с.) |