Безопасность исключений
Безопасность исключений — это состояние корректной работы кода при возникновении исключений. [1] Чтобы обеспечить безопасность исключений, разработчики стандартной библиотеки C++ разработали набор уровней безопасности исключений , договорных гарантий поведения операций структуры данных в отношении исключений. Разработчики библиотек и клиенты могут использовать эти гарантии при анализе правильности обработки исключений . Уровни безопасности исключений в равной степени применимы к другим языкам и механизмам обработки ошибок. [2]
История
[ редактировать ]Как пишет Дэвид Абрахамс , «никто никогда не говорил о «безопасности от ошибок» до того, как в C++ появились исключения». [3] Этот термин появился в качестве темы публикаций в JTC1/SC22/WG21 , комитете по стандартизации C++, еще в 1994 году. [4] Безопасность исключений для стандартной библиотеки C++ была впервые формализована для STLport Абрахамсом, установив различие между базовой безопасностью и строгой безопасностью. [5] В более позднем предложении это было распространено на современные гарантии «базовый/сильный/небросок». [6]
Фон
[ редактировать ]Исключения представляют собой форму нелокального потока управления, при котором исключение может «всплывать» из вызываемой функции. Это всплытие может вызвать ошибку безопасности исключений, нарушая инварианты изменяемой структуры данных, как показано ниже: [7]
- Шаг операции над изменяемой структурой данных изменяет данные и нарушает инвариант.
- Выбрасывается исключение, и управление «всплывает», пропуская остальную часть кода операции, которая восстановит инвариант.
- Исключение перехватывается и восстанавливается, или
finally
блок введен - Структура данных с нарушенным инвариантом используется кодом, который предполагает инвариант, что приводит к ошибке.
Код с такой ошибкой, как приведенная выше, можно назвать «небезопасным по исключениям». [7]
Классификация
[ редактировать ]Стандартная библиотека C++ предоставляет несколько уровней безопасности исключений (в порядке убывания безопасности): [8]
- Гарантия отсутствия бросков , также известная как прозрачность сбоев : операции гарантированно завершаются успешно и удовлетворяют всем требованиям даже в исключительных ситуациях. Если возникнет исключение, оно будет обработано внутри компании и не будет замечено клиентами.
- Строгая безопасность исключений , также известная как семантика фиксации или отката : операции могут завершиться неудачно, но неудачные операции гарантированно не будут иметь побочных эффектов, оставляя исходные значения нетронутыми. [9]
- Базовая безопасность исключений : частичное выполнение неудачных операций может привести к побочным эффектам, но все инварианты сохраняются. Любые сохраненные данные будут содержать допустимые значения, которые могут отличаться от исходных значений. Утечки ресурсов (включая утечки памяти ) обычно исключаются инвариантом, утверждающим, что все ресурсы учитываются и управляются.
- Безопасность без исключений : Никаких гарантий не предоставляется.
Обычно для написания надежного кода требуется хотя бы базовая безопасность исключений. Иногда бывает трудно достичь более высокого уровня безопасности, и это может повлечь за собой накладные расходы из-за дополнительного копирования. Ключевым механизмом безопасности исключений является finally
предложение или аналогичный синтаксис обработки исключений , который гарантирует, что определенный код всегда запускается при выходе из блока, в том числе при возникновении исключений. В нескольких языках есть конструкции, упрощающие это, в частности, использование шаблона расположения , называемого using
, with
, или try
-с-ресурсами.
Пример
[ редактировать ]Рассмотрим интеллектуальный векторный тип, такой как C++. std::vector
или Java ArrayList
. Когда предмет x
добавляется к вектору v
, вектор должен фактически добавить x
во внутренний список объектов и обновите поле счетчика, в котором указано, сколько объектов находится в v
. Также может потребоваться выделить новую память, если имеющейся емкости недостаточно.
Альтернативы безопасности исключений:
- Гарантия отсутствия броска
- Реализуется путем обеспечения того, чтобы распределение памяти никогда не прерывалось, или путем определения
insert
поведение функции при сбое выделения (например, если функция возвращает логический результат, указывающий, имела ли место вставка). - Надежная безопасность исключений
- Реализуется путем сначала выполнения необходимого выделения, а затем замены буферов, если ошибок не обнаружено ( идиома копирования и замены ). В этом случае либо вставка
x
вv
преуспевает, илиv
остается неизменным, несмотря на сбой распределения. - Базовая безопасность исключений
- Реализовано путем обеспечения того, чтобы поле счетчика гарантированно отражало окончательный размер
v
. Например, если произошла ошибка,insert
функция может полностью освободитьv
и сбросим поле счетчика в ноль. В случае сбоя утечка ресурсов не происходит, ноv
старое значение не сохраняется. - Без исключений безопасность
- Ошибка вставки может привести к повреждению содержимого в
v
, неверное значение в поле count или утечка ресурса .
Ссылки
[ редактировать ]- ^ Крайтон, Алекс (24 июля 2015 г.). «Rust RFC: стабилизировать catch_panic» . Язык программирования Rust . Проверено 26 мая 2022 г.
Код защищен от исключений, если он работает правильно, даже если вызываемые им функции вызывают исключения.
- ^ Лау, Рон (10 ноября 2020 г.). «Безопасность исключений в мире JS» . Середина .
- ^ Дэйв Абрахамс (2000). Безопасность исключений в универсальных компонентах . Общее программирование . Конспекты лекций по информатике . Том. 1766. Спрингер . стр. 69–79. дои : 10.1007/3-540-39953-4_6 . ISBN 978-3-540-41090-4 . Проверено 29 августа 2008 г.
- ^ Колвин, Грегори (1994). «Исключения, безопасные для исключений» (PDF) . Документы комитета по стандартам C++ . Проверено 17 декабря 2021 г.
- ^ Абрахамс, Дэвид. «STLport: обработка исключений» . www.stlport.org . Проверено 17 декабря 2021 г.
- ^ Абрахамс, Дэйв; Колвин, Грег. «Обеспечение исключений стандартной библиотеки C++» (PDF) . Документы комитета по стандартам C++ . Проверено 17 декабря 2021 г.
- ^ Jump up to: а б Крайтон, Алекс (24 июля 2015 г.). «Rust RFC: стабилизировать catch_panic» . Язык программирования Rust . Проверено 26 мая 2022 г.
- ^ Бьерн Страуструп (1997). Приложение E: Безопасность исключений стандартной библиотеки в «Языке программирования C ++» (PDF) (3-е изд.). Аддисон-Уэсли. ISBN 0-201-88954-4 .
- ^ Остерн, Мэтт (30 мая 1997 г.). «Стандартная политика исключений библиотеки» . Документы комитета по стандартам C++ . Проверено 26 мая 2022 г.
Внешние ссылки
[ редактировать ]- Херб Саттер: Исключительный C ++: 47 инженерных головоломок, проблем программирования и решений, 2000 г.
- Джон Калб: Исключительно безопасное программирование на C++ с помощью C++Now! Презентации 2012 года по безопасности исключений.
- Соответствующее обсуждение Stackoverflow: C++: вы (действительно) пишете код, безопасный для исключений?