Обробка винятків
Обро́бка ви́нятків (англ. exception handling) — механізм мов програмування, призначений для обробки помилок часу виконання і інших можливих проблем (винятків), які можуть виникнути при виконанні програми.
В цілому, при виникненні виняткової ситуації, управління передається деякому заздалегідь призначеному обробникові. У деяких мовах, обробник може відновити виконання програми з місця виникнення винятку. Таким чином, обробка помилок передається на вищий рівень і забезпечується можливість так званого нелокального виходу, тобто передачі управління на деяку «віддалену», можливо заздалегідь невідому, точку програми через довільне число викликів функцій.
Зміст |
Переваги і недоліки [ред.]
Винятки надають основні переваги при розробці окремих компонентів, коли розробник компоненту не знає, як потрібно обробити виняток і залишає написання обробника винятку користувачеві його компонента.
Використання винятків в цілях контролю помилок підвищує читаність коду, оскільки дозволяє відокремити обробку помилок від самого алгоритму, і полегшує програмування і використання компонентів інших розробників.
Основний недолік винятків — в їхній невисокій швидкості. У місцях програми, критичних за швидкістю, не варто порушувати і обробляти винятки.
В складних програмах виникають великі «нагромадження» операторів try … finally і try … catch (try … except), але без застосування механізму обробки винятків аналогічна за функціональністю програма виглядала б ще більше захаращеною.
Підтримка в різних мовах [ред.]
Більшість сучасних мов програмування, таких як ActionScript, Ada, C++, Common Lisp, D, Delphi, Eiffel, Java, JavaScript, OBJECTIVE-C, OCaml, 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). У результаті, компілятор «примушує» писати обробники винятків навіть там, де вони, здавалося б, не потрібні.
| Ця стаття не містить посилань на джерела. (червень 2011) |

