Обробка винятків в c

Мова С представляє програмісту дуже обмежені можливості обробки винятків, що виникли при роботі програми. В цьому відношенні С ++ набагато більш розвинутою С. Тут у програміста істотно більші можливості щодо безпосередньої обробці виключень. Комітет з розробки стандартів С ++ надав дуже просту, але потужну форму обробки винятків.

Темні дні З

Типова функція, написана на С, виглядає приблизно так:

Виглядає не дуже, чи не так? Ви цілком і повністю залежите від значень, які повертають вам функції і для кожної помилки вам постійно потрібен код, який її обробляє. Якщо ви, скажімо, в функції працюєте хоча б з 10 покажчиками (рапределяете пам'ять, звільняєте її і т.д.), то напевно половину коду функції буде займати код обробки помилок. Така ж ситуація буде в коді, що викликає цю функцію, так як тут також потрібно обробити всі повертаються коди помилок.

Try-catch-throw

Давайте ж розберемо основи обробки виключень в С ++. Щоб комфортно працювати з винятками в С ++ вам потрібно знати лише три ключових слова:

  • try (намагатися) - початок блоку винятків;
  • catch (зловити) - початок блоку, "ловить" виключення;
  • throw (кинути) - ключове слово, "створює" ( "збудливу") виняток.

А тепер приклад, який демонструє, як застосувати те, що ви дізналися:

Якщо виконати цей фрагмент коду, то ми отримаємо наступний результат:

Тепер закоментіруйте рядок throw 1; і функція видасть такий результат:

Як бачите все дуже просто, але якщо це застосувати з розумом, такий підхід здасться вам дуже потужним засобом обробки помилок. Catch може "ловити" будь-який тип даних, так само як і throw може "кинути" дані будь-якого типу. Тобто throw AnyClass (); буде правильно працювати, так само як і catch (AnyClass d) <>;.

Як вже було сказано, catch може "ловити" дані будь-якого типу, але зовсім не обов'язково при це вказувати змінну. Тобто прекрасно працюватиме що-небудь типу цього:

Так само можна "зловити" і все виключення:

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

Створення "винятків

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

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

Перевантаження глобальних операторів new / delete

А зараз хотілося б відправити вас до статті "Як виявити витік пам'яті". У ній розповідається, як виявити неправильне управління розподілом пам'яті у вашій програмі. Ви можете запитати, при чому тут перевантаження операторів? Якщо перевантажити стандартні new і delete, то відкриваються широкі можливості по відстеженню помилок (причому помилок часто критичних) за допомогою винятків. наприклад:

Це, на перший погляд, здаються довшими, ніж стандартна перевірка в С "а дорівнює NULL?", Проте якщо в програмі виділяється десяток динамічних змінних, то такий метод виправдовує себе.

Оператори throw без параметрів

Отже, ми побачили, як новий метод обробки помилок зручний і простий. Блок try-catch може містити вкладені блоки try-catch і якщо не буде визначено відповідного оператора catch на поточному уровен вкладення, виняток буде спіймано на більш високому рівні. Єдина річ, про яку ви повинні пам'ятати, - це те, що оператори, які йдуть за throw, ніколи не виконаються.

Такий метод може застосовуватися у випадках, коли не потрібно передавати ніяких даних в блок catch.

додаток

Наведемо приклад, як все вищевикладене може бути використано в конкретному додатку. Припустивши, у вас в програмі є клас cMain і екземпляр цього класу Main: class cMain ; cMain Main;

А в функції main () або WinMain () ви можете використовувати цей клас як-небудь так:

Основний цикл програми може виглядати приблизно так:

висновок

Метод обробки винятків, наведений у статті, є зручним і потужним засобом, однак тільки вам вирішувати, використовувати його чи ні. Одне можна скачати точно - наведений метод полегшить вам життя. Якщо хочете дізнатися про винятки трохи більше, подивіться публікацію Deep C ++ на сервері MSDN.

Схожі статті