Обро́бка ви́нятків (також опрацьо́вування (обробля́ння) винятко́вих ситуа́цій[1], англ. exception handling) — механізм мов програмування, призначений для обробки помилок часу виконання й інших можливих проблем (винятків), які можуть виникнути під час виконання програми.

Загалом під час виникнення виняткової ситуації, керування передається деякому заздалегідь призначеному обробникові (опрацьовувачу). У деяких мовах, обробник може відновити виконання програми з місця виникнення винятку. Таким чином, обробка помилок передається на вищий рівень і забезпечується можливість так званого нелокального виходу, тобто передачі керування на деяку «віддалену», можливо заздалегідь невідому, точку програми через довільне число викликів функцій.

Переваги та недоліки ред.

Винятки надають основні переваги під час розробки окремих компонентів, коли розробник компонента не знає, як потрібно обробити виняток і залишає написання обробника винятку користувачеві його компонента.

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

Основний недолік винятків — у їхній невисокій швидкості. У місцях програми, критичних за швидкістю, не варто порушувати й обробляти винятки.

У складних програмах виникають великі «нагромадження» операторів try … finally і try … catch (try … except), але без застосування механізму обробки винятків аналогічна за функціональністю програма виглядала б ще більше захаращеною.

Підтримка в різних мовах ред.

Більшість сучасних мов програмування, таких як ActionScript, Ada, C++, Common Lisp, D, Object Pascal, Eiffel, Java, JavaScript, Objective-C, Objective Caml, Ruby, PHP (з версії 5), Python, SML, Глагол, всі мови платформи .NET тощо, мають вбудовану підтримку обробки винятків. У цих мовах, під час виникнення виняткової ситуації (точніше, винятку, підтримуваного мовою), відбувається розкручування стека викликів до першого обробника винятків відповідного типу, і керування передається обробникові.

За винятком незначних відмінностей у синтаксисі, існує лише пара варіантів обробки винятків. У найпоширенішому з них виняткова ситуація генерується спеціальним оператором (throw або raise) з об'єктом-винятком. Водночас конструювання такого об'єкта само собою викиду винятку не спричиняє. Область дії обробників починається спеціальним ключовим словом try або просто мовним маркером початку блоку (наприклад, begin) і закінчується перед описом обробників (catch, except, resque). Обробників може бути кілька, один за одним, і кожен може вказувати тип винятку, який він обробляє.

Деякі мови також допускають спеціальний блок (else), який виконується, якщо жодного винятку не згенерувано у відповідній області дії. Частіше зустрічається можливість безумовного виконання коду (finally, ensure), навіть у разі, якщо виняток було викинуто, але не оброблено. Помітним винятком є С++, де такої конструкції немає. Замість неї використовується автоматичний виклик деструкторів об'єктів. Водночас існують нестандартні розширення С++, що підтримують і функціональність finally (наприклад в MFC).

Загалом обробка винятків може виглядати таким чином (у деякій абстрактній мові):

try {
  line = console.readLine();
  if (line.length() == 0)
    throw new EmptyLineException("Рядок, прочитаний з консолі, пустий!");

  console.printLine("Привіт, %s!" % line);
}
catch (EmptyLineException exception) {
  console.printLine("Привіт!");
}
catch (Exception exception) {
  console.printLine("Помилка: " + exception.message());
}
else {
  console.printLine("Програма виконана без виняткових ситуацій");
}
finally {
  console.printLine("Програма завершена");
}

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

У деяких мовах, наприклад Сі або Perl, немає вбудованої обробки винятків.

Винятки, що перевіряються ред.

Спочатку (наприклад, у C++), винятки не були обов'язковими для обробки. Якщо якийсь виняток не обробляється, тобто якщо для нього немає обробника в стеку виклику, або обробник викинув виняток наново, то виконання програми уривається.

У новіших мовах, наприклад у Java, разом з «класичними» з'явилися винятки, що перевіряються. Обробка таких винятків перевіряється компілятором. Метод, у якому може виникнути виняток (зокрема й у методах, що викликаються) зобов'язаний або обробити його, або оголосити, що може викинути[куди?] такий виняток.

Переваги та недоліки ред.

Винятки, що перевіряються, знижують кількість ситуацій, коли виняток, який міг бути обробленим, викликав критичну помилку в програмі, оскільки за наявністю обробників стежить компілятор. Це може бути особливо корисно, якщо метод, який не міг викидати виняток типу X став це робити: компілятор автоматично відстежить усі випадки його використання і перевірить наявність відповідного обробника.

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

У результаті, багато бібліотек оголошують усі методи як такі, що викидають деякий суперклас винятків (наприклад, Exception). У результаті, компілятор «примушує» писати обробники винятків навіть там, де вони, здавалося б, не потрібні.

Примітки ред.

  1. О. Кочерга, Є. Мейнарович, Англійсько-українсько-англійський словник наукової мови (фізика та споріднені науки). Частина І англійсько-українська 2010р.

Див. також ред.