67359

Обробка виняткових ситуацій

Лекция

Информатика, кибернетика и программирование

Розглянемо механізми оброблення різних виняткових ситуацій. Виняткова ситуація (або виняток) – це помилка, яка виникає у процесі виконання програми. Використовуючи С++-підсистему оброблення виняткових ситуацій, такі помилки легко можна виправляти. Їх виникнення під час роботи коду програми автоматично...

Украинкский

2014-09-07

101 KB

6 чел.

Лекція № 22

Тема: Обробка виняткових ситуацій

План

  1.  Основні особливості оброблення виняткових ситуацій
  2.  Системні засоби оброблення винятків

  1.  Основні особливості оброблення виняткових ситуацій

    Розглянемо механізми оброблення різних виняткових ситуацій. Виняткова ситуація (або виняток) – це помилка, яка виникає у процесі виконання програми. Використовуючи С++-підсистему оброблення виняткових ситуацій, такі помилки легко можна виправляти. Їх виникнення під час роботи коду програми автоматично призводить до виклику так званого обробника винятків. При цьому програміст не забезпечує перевірку результату виконання кожної конкретної операції або функції "вручну". У цьому й полягає принципова перевага системи оброблення винятків, оскільки саме вона відповідає за код оброблення помилок, який раніше доводилося "вручну" вводити в громіздкі програми.

   Керування С++-механізмом оброблення винятків тримається на трьох ключових словах: try, catch і throw. Вони утворюють взаємопов'язану підсистему, у якій використання одного з них припускає застосування іншого. Спершу спробуємо отримати загальне уявлення про ті вигоди, які вони надають програмісту під час оброблення виняткових ситуацій. 

   Оброблення винятків-це системні засоби, за допомогоюяких программа може справитися з помилками тривалості виконання.

  1.   Системні засоби оброблення винятків

   Робота системних засобів оброблення винятків полягає в такому. Програмні настанови, які потрібно проконтролювати на предмет винятків, поміщаються в try-блок. Якщо виняток (тобто помилка) таки виникає у процесі виконання блоку, то він дає знати про себе шляхом викидання певної інформації (за допомогою ключового слова throw). Цей викинутий виняток можна перехопити програмно за допомогою catch-блоку і відповідно обробити.

   Настанова throw генерує виняток, який перехоплюється catch-настановою.

   Отже, програмні настанови, у яких можливе виникнення виняткових ситуацій, мають виконуватися у межах try-блоку. Будь-яка функція, що викликається з цього try-блоку, також піддається контролю. Винятки, які можуть бути викинуті контрольованими настановами, перехоплюються catch-настановою, що йде безпосередньо за try-блоком, у якому фіксуються ці "викиди".

    

    Загальний формат try- і catch-блоків має такий вигляд:

try

{    

     // try-блок (блок коду програми, що підлягає перевірці на наявність помилок)

}   

catch(aType arg)

{

     // catch-блок (обробник винятків типу aType)

}

catch(bType arg)

{

     // catch-блок (обробник винятків типу bType)

}

catch(cType arg)

{

     // catch-блок (обробник винятків типу cType)

}

//....

catch(nType arg)

{

     // catch-блок (обробник винятків типу nType)

}

   Блок try повинен містити програмні настанови, який, на Вашу думку, мають перевірятися на предмет виникнення помилок. Цей блок може містити тільки декілька настанов певної функції або охоплювати весь код функції main() (у цьому випадку, по суті, "під ковпаком" системи оброблення винятків знаходитиметься вся програма).

   Після "викиду" виняток перехоплюється відповідною настановою catch, яка здійснює його оброблення. З одним try-блоком може бути пов'язана не одна, а декілька catch-настанов. Яка саме з них буде виконуватися, визначається типом винятку. Іншими словами, виконуватиметься та catch-настанова, тип винятку якої (тобто тип даних, який задається в catch-настанові) збігається з типом згенерованого винятку (а всі інші будуть проігноровані). Після перехоплення винятку параметр arg прийме його значення. Так само можуть перехоплюватися дані будь-яко-

го типу, в т.ч. об'єкти класів, що були створені програмістом.

Щоб виняток перехоплювати, необхідно забезпечити його «викид» в try-блоці.

   Загальний формат настанови throw має такий вигляд:

throw exception;

   У  цьому записі за допомогою елемента exception задається виняток, що згенерується настановою throw. Якщо цей виняток підлягає перехопленню, то настанова throw має виконуватися або в самому блоці try, або в будь-якій функції, яка викликається з нього (тобто прямо або опосередковано).

   Якщо у програмі забезпечується «викид» винятку, для якого не передбачено відповідну catch-настанову, то відбудеться аварійне завершення роботи коду програми, що викликається стандартною бібліотечною функцією terminate(). За замовчуванням функція terminate() викликає функцію abort() для зупинки програми, але при бажанні можна визначити власний обробник для її завершення.

   Розглянемо простий приклад оброблення винятків засобами мови C++.

Приклад. Демонстрація механізму оброблення винятків

void main()

{

cout << "Po4atok" << endl;

 try

{      // Початок try-блоку

 cout << "Y try-bloci" << endl;

 throw 99;           // Генерування помилки

 cout << "Cja nastanova ne byde vukonana";

   }

 catch(int c)

{      // Перехоплення помилки

 cout << "Zna4ennja perehoplenogo vunjatky = : " << c << endl;

              }

cout << "Kinec programu";

}

  

   Внаслідок виконання ця програма відображає на екрані такі результати:

Початок.

У try-блоці

Значення перехопленого винятку дорівнює: 99

Кінець програми

 

   Розглянемо уважно код цієї програми. Як бачите, тут try-блок містить три настанови, а настанова catch(int c) призначена для оброблення винятку цілочисельного типу. У цьому try-блоці виконуються тільки дві з трьох настанов: cout і throw. Після генерування винятку керування передається catch-виразу, при цьому виконання try-блоку припиняється. Необхідно розуміти, що catch-настанова не викликається, а просто з неї продовжується виконання програми після "викиду" винятку. Стек програми автоматично налаштовується відповідно до ситуації, що виникла. Тому cout-настанова, що знаходиться після throw-настанови, ніколи не виконається.

    Після виконання catch-блоку керування програмою передається настанові, що знаходиться за цим блоком. Тому обробник винятків має виправити помилку, що спричинила його виникнення, щоб програма могла нормально продовжити виконання. У випадках, коли помилку виправити не можна, catch-блок зазвичай завершується зверненням до функцій exit() або abort().

    Як уже зазначалося вище, тип винятку повинен збігатися з типом, заданим у catch-настанові. Наприклад, якщо в попередній програмі тип винятку int, який було вказано в catch-виразі, замінити типом double, то виняток не перехопиться, тобто відбудеться аварійне завершення роботи коду програми. Ось як виглядають наслідки внесення такої зміни.

Приклад.  Демонстрація не коректної роботи коду програми

void main()

{

cout << "Po4atok" << endl;

 try

{      // Початок try-блоку

 cout << "Y try-bloci" << endl;

 throw 99;           // Генерування помилки

 cout << "Cja nastanova ne byde vukonana";

   }

 catch(double c)

{      // Перехоплення помилки

 cout << "Zna4ennja perehoplenogo vunjatky = : " << c << endl;

              }

cout << "Kinec programu";

}

  Внаслідок виконання ця програма відображає на екрані такі результати:

Початок.

У try-блоці

Ця настанова не буде виконана.

  Такі результати виконання цієї програми пояснюються тим, що винятки ціло-

чисельного типу не перехоплює настанова catch(double c).

Тема: Використання функцій exit() і abort() 

   Функції exit() і abort() входять до складу стандартної бібліотеки C++ і їх часто використовують при програмуванні мовою C++. Обидві вони забезпечують завершення роботи коду програми, але відбувається це по-різному.

   Виклик функції exit() негайно приводить до "правильного" припинення роботи коду програми1. Зазвичай цей спосіб завершення роботи використовують для зупинки програми під час виникнення непоправної помилки, яка робить подальше її виконання безглуздим або небезпечним. Для використання функції exit() потрібно залучити до програми заголовок <cstdlib>. Її прототип має такий вигляд:

void exit(int status);

   Оскільки функція exit() викликає негайне завершення роботи коду програми, то вона не передає керування процесу, який її викликає, і не повертає ніякого значення. Проте процесу, що її викликає, як код завершення, передається значення параметра status. За домовленістю нульове значення параметра status вказує на успішне завершення роботи коду програми. Будь-яке інше його значення свідчить про те, що завершення роботи коду програми є помилковим. Для індикації успішного завершення роботи можна також використовувати константу EXIT_SUCCESS, а для індикації помилки – константу EXIT_FAILURE. Ці константи визначаються у заголовку <cstdlib>.

   Прототип функції abort() має такий вигляд:

 void abort();

   Функція abort() викликає негайне завершення роботи коду програми. Але, на відміну від функції exit(), вона не повертає операційній системі ніякої інформації про статус завершення роботи коду програми і не здійснює стандартної ("правильної") послідовності дій під час зупинки програми. Для використання функції abort() потрібно залучити до програми заголовок <cstdlib>. Функцію abort() можна назвати аварійним "стоп-краном" для С++-програми. Її необхідно використовувати тільки після виникнення непоправної помилки.

   Останнє повідомлення про аварійне завершення роботи коду програми (Abnormal program termination) може відрізнятися від наведеного в результатах виконання попереднього прикладу. Це залежить від використовуваного Вами компілятора. Виняток, що генерує функція, яку було викликано з try-блоку, можна перехопити цим самим try-блоком. Розглянемо, наприклад, таку цілком коректну програму.

Приклад. Демонстрація механізму генерування винятку функцією, що викликається з try-

                 блоку

void Xtest(int test)

{

cout << "У функції Xtest() значення test дорівнює: " << test << endl;

if(test) throw test;

}

void main()

{

cout << "Початок" << endl;

try

{    // Початок try-блоку

 cout << "У try-блоці" << endl;

 Xtest(0);

 Xtest(1);

 Xtest(2);

}

 

             catch(int c)

{      // Перехоплення помилки

 cout << "Значення перехопленого винятку дорівнює: ";

 cout << c << endl;

}

cout << "Кінець програми";

}

   Внаслідок виконання ця програма відображає на екрані такі результати:

Початок.

У try-блоці

У функції Xtest() значення test дорівнює: 0

У функції Xtest() значення test дорівнює: 1

Значення перехопленого винятку дорівнює: 1

Кінець програми

    Блок try можна локалізувати у межах роботи самої функції. У цьому випадку під час кожного її виконання запускається і оброблення винятків, пов'язаних з роботою цією функцією. Розглянемо таку навчальну програму.

Приклад. Демонстрація механізму локалізації блоку try у рамках роботи самої функції

    // Функціонування блоків try/catch поновлюється під час кожного входження у функцію.

void Xhandler(int test)

{

try

{

 if(test) throw test;

}

catch(int c)  

{

 cout << "Перехоплення! Виняток №: " << c << endl;

}

}

void main()

{

cout << "Початок" << endl;

Xhandler(1);

Xhandler(2);

Xhandler(0);

Xhandler(3);

cout << "Кінець програми";

}

   Внаслідок виконання ця програма відображає на екрані такі результати:

Початок.

Перехоплення! Виняток №: 1

Перехоплення! Виняток №: 2

Перехоплення! Виняток №: 3

Кінець програми

   Як бачите, програма згенерувала три різних винятки. Після кожного винятку функція Xhandler() передавала керування у функцію main(). Коли вона знову викликалася, поновлювалося і оброблення винятків.

   У загальному випадку try-блок відновлює своє функціонування під час кожного входу в нього. Тому try-блок, який є частиною циклу, запускатиметься при кожному повторенні цього циклу.


 

А также другие работы, которые могут Вас заинтересовать

36500. Розподіл молекул у полі сил. Формула Больцмана. Барометрична формула. Дослід Перрена по визначенню числа Авогадро 258.99 KB
  Наявність зовнішньої сили призведе до того що молекули у просторі будуть розміщені неоднорідно отже створюватимуть у різних точках простору різний тиск. Для осі ця різниця тисків на грані паралелепіпеда перпендикулярні осі де зміна тиску на одиницю довжини; зміна тиску на бічних гранях; площа граней. Згадаємо що ; відповідно повні диференціали зміни тиску та потенціальної енергії. Повний диференціал зміни тиску газу дорівнює добутку концентрації молекул на повний диференціал зміни потенціальної енергії молекули взятому з...
36501. Біноміальний розподіл 536.29 KB
  Кількість частинок у ньому . Кількість комірок у обємі причому завжди виконується умова тобто частинка завжди знайде собі місце. Виділимо у обємі менший фіксований обєм і будемо шукати імовірність того що кількість частинок потрапить у цей обєм. Кількість комірок у обємі повинно бути принаймні не меншою за щоб усі частинки могли розміститись.
36502. Тиск газу з точки зору молекулярно-кінетичної теорії. Основне рівняння кінетичної теорії ідеального газу. Зв’язок між тиском газу та середньою кінетичною енергією газових молекул 205.51 KB
  Основне рівняння кінетичної теорії ідеального газу. Звязок між тиском газу та середньою кінетичною енергією газових молекул. Розрахуємо тиск газу на стінку посудини.
36503. Рівність середньокінетичних енергій молекул газу при взаємодії двох газів із непроникливою стінкою 464.46 KB
  І тепер перейдемо до вивчення елементів симетрії кристалу. Елементи симетрії кристалів. Симетрія це властивість тіла суміщатися із самим собою під час деяких операцій або перетворень симетрії. З однією операцією симетрії ми вже зустрічались на початку лекції це трансляційна симетрія.
36504. Обертальний броунівський рух 244.07 KB
  Такі обертові рухи можна зіставити з коливаннями маленького дзеркальця підвішеного на тонкій пружній дротинці в газі. Величина оскільки дзеркальце рівну кількість разів повертається за годинниковою стрілкою і проти неї тому цим доданком можна знехтувати. Дзеркальце у газі можна розглядати як величезну броунівську частинку так само як і поршень коли ми розглядали газокінетичний зміст температури. Отже за значеннями макроскопічних параметрів якими є температура модуль кручення дротинки та середнє значення квадрату кутового відхилення...
36505. Розподіл молекул за абсолютними значеннями швидкості. Функція розподілу Максвелла 256.56 KB
  Тепер вже швидкість беремо за абсолютним значенням отже вона буде додатньою. Отже на графіку наведені залежності для кількох температур. Отже сформульований постулат стверджує що процес Клаузіуса неможливий. Отже узагальнений постулат ТомсонаПланка “Неможливо створити періодично діючу машину єдиним результатом дії якої було б виконання роботи лише за рахунок охолодження нагрівачаâ€.
36506. Якісне пояснення температурної залежності теплоємності газів на підставі квантових уявлень 630.47 KB
  Звідки може брати енергію осцилятор Він її отримує при зіткненнях. Але прийняти будьяку енергію осцилятор не може. Він приймає енергію тільки кратну і переходить на один із наступних енергетичних рівнів на рисунку. Наша молекула зможе прийняти необхідну енергію лише від молекули із заштрихованої області.
36507. Потік газових молекул на стінку. Закон косинусу 191.07 KB
  Закон косинусу У багатьох задачах потрібно враховувати кількість молекул що падає на стінку посудини. На стінку впадуть лише ті молекули напрямки яких направлені у бік виділеної ділянки. Нам необхідно знати розподіл молекул за напрямками швидкостей.
36508. Молекулярні пучки. Зміна кількості молекул у пучці 188.18 KB
  Зміна кількості молекул у пучці внаслідок зіткнень з молекулами газу Нехай маємо джерело молекулярного пучка. Нагадаю : молекулярний пучок це вузький різко окреслений струмінь атомів що рухаються в одному напрямку і не взаємодіють між собою. Молекулярний пучок рухається у газі вздовж осі .