Spec-Zone.ru › C++

Исключения

Обработка исключений предоставляет способ передачи управления и информации из некоторой точки выполнения программы обработчику, связанному с точкой, ранее пройденной при выполнении (иными словами, обработка исключений передаёт управление вверх по стеку вызовов).

Вычисление выражения throw вызывает исключение. Исключения также могут вызываться в других контекстах.

Чтобы исключение было перехвачено, выражение throw должно находиться внутри блока try, а блок try должен содержать обработчик, соответствующий типу объекта исключения.

При объявлении функции могут указываться следующие спецификации, ограничивающие типы исключений, которые может вызвать функция:

  • динамические спецификации исключений
(до C++17)
  • спецификации noexcept
(начиная с C++11)

Ошибки, возникающие при обработке исключений, обрабатываются с помощью std::terminate и std::unexpected(до C++17).

Использование

Хотя выражение throw можно использовать для передачи управления произвольному блоку кода выше по стеку выполнения по произвольным причинам (аналогично std::longjmp), его предполагаемое назначение — обработка ошибок.

Обработка ошибок

Исключения используются для сигнализации об ошибках из функций, причём под «ошибками» обычно понимаются только следующие ситуации[1][2][3]:

  1. Невыполнение постусловий, например невозможность создать корректный объект возвращаемого значения.
  2. Невыполнение предусловий другой функции, которую необходимо вызвать.
  3. (для непубличных функций-членов) Невозможность установить или восстановить инвариант класса.

В частности, отсюда следует, что о сбоях конструкторов (см. также RAII) и большинства операторов следует сообщать посредством исключений.

Кроме того, так называемые функции с широким контрактом используют исключения для обозначения недопустимых входных данных. Например, у std::basic_string::at нет предусловий, но он вызывает исключение, чтобы указать на выход индекса за границы.

Безопасность исключений

После того как функция сообщила об ошибке, могут предоставляться дополнительные гарантии относительно состояния программы. Обычно выделяют следующие четыре уровня гарантий безопасности исключений[4][5][6], каждая из которых строже предыдущей:

  1. Гарантия отсутствия исключений (или безотказности) — функция никогда не вызывает исключений. Гарантия отсутствия исключений (ошибки сообщаются другими способами или скрываются) ожидается от деструкторов и других функций, которые могут вызываться при раскрутке стека. Деструкторы по умолчанию являются noexcept.(начиная с C++11) Гарантия безотказности (функция всегда завершается успешно) ожидается от операций обмена, перемещающих конструкторов и других функций, используемых теми, которые предоставляют строгую гарантию безопасности исключений.
  2. Строгая гарантия безопасности исключений — если функция вызывает исключение, состояние программы откатывается к состоянию, существовавшему непосредственно перед вызовом функции (например, std::vector::push_back).
  3. Базовая гарантия безопасности исключений — если функция вызывает исключение, программа остаётся в корректном состоянии. Утечки ресурсов отсутствуют, а инварианты всех объектов сохраняются.
  4. Отсутствие гарантии безопасности исключений — если функция вызывает исключение, программа может оказаться в некорректном состоянии: возможны утечки ресурсов, повреждение памяти или другие ошибки, нарушающие инварианты.

Кроме того, обобщённые компоненты могут предоставлять гарантию нейтральности к исключениям: если исключение возникает в параметре шаблона (например, в функциональном объекте Compare из std::sort или в конструкторе T в std::make_shared), оно передаётся вызывающему коду без изменений.

Объекты исключений

В качестве объектов исключений можно выбрасывать объекты любых полных типов и указатели cv на void, однако все функции стандартной библиотеки выбрасывают безымянные объекты по значению, а типы этих объектов прямо или косвенно наследуются от std::exception. Пользовательские исключения обычно следуют этому шаблону.[7][8][9]

Чтобы избежать ненужного копирования объекта исключения и срезки объекта, обработчикам рекомендуется перехватывать исключения по ссылке.[10][11][12][13]

Примечания

Макрос проверки поддержки функции Значение Стандарт Функция
__cpp_constexpr_exceptions 202411L (C++26) исключения constexpr

Внешние ссылки

  1. H. Sutter (2004) «When and How to Use Exceptions» в Dr. Dobb's
  2. H. Sutter, A. Alexandrescu (2004), «C++ Coding Standards», пункт 70
  3. Руководство по основам C++ I.10: Используйте исключения, чтобы сообщать о невозможности выполнить требуемую задачу
  4. B. Stroustrup (2000), «The C++ Programming Language» приложение E
  5. H. Sutter (2000) «Exceptional C++»
  6. D. Abrahams (2001) «Exception Safety in Generic Components»
  7. D. Abrahams (2001) «Error and Exception Handling»
  8. isocpp.org Super-FAQ «What should I throw?»
  9. Руководство по основам C++ E.14: Используйте специально разработанные пользовательские типы в качестве исключений (а не встроенные типы)
  10. Руководство по основам C++ E.15: Выбрасывайте по значению, перехватывайте исключения из иерархии по ссылке
  11. S. Meyers (1996) «More Effective C++», пункт 13
  12. isocpp.org Super-FAQ «What should I catch?»
  13. H. Sutter, A. Alexandrescu (2004) «C++ Coding Standards», пункт 73

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/exceptions

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API