Состояние кода, работающего правильно при возникновении исключений
Безопасность исключений — это состояние кода, работающего правильно при возникновении исключений. [1] Чтобы обеспечить безопасность исключений, разработчики стандартной библиотеки C++ разработали набор уровней безопасности исключений , договорных гарантий поведения операций структуры данных в отношении исключений. Разработчики библиотек и клиенты могут использовать эти гарантии при рассуждениях о корректности обработки исключений . Уровни безопасности исключений в равной степени применимы к другим языкам и механизмам обработки ошибок. [2]
История
Как пишет Дэвид Абрахамс , «никто никогда не говорил об «ошибочной безопасности» до того, как в C++ появились исключения». [3] Этот термин появился как тема публикаций в JTC1/SC22/WG21 , комитете по стандарту C++, еще в 1994 году. [4] Безопасность исключений для стандартной библиотеки C++ была впервые формализована для STLport Абрахамсом, установившим различие между базовой безопасностью и сильной безопасностью. [5] Это было распространено на современные гарантии basic/strong/nothrow в более позднем предложении. [6]
Фон
Исключения предоставляют форму нелокального потока управления, в котором исключение может «всплывать» из вызываемой функции. Это всплытие может вызвать ошибку безопасности исключений, нарушая инварианты изменяемой структуры данных, как показано ниже: [7]
Шаг операции над изменяемой структурой данных изменяет данные и нарушает инвариант.
Выдается исключение, и управление «всплывает», пропуская оставшуюся часть кода операции, которая должна восстановить инвариант.
Исключение перехватывается и устраняется, или finallyвводится блокировка
Структура данных с нарушенным инвариантом используется кодом, который предполагает инвариант, что приводит к ошибке
Код с такой ошибкой, как вышеприведенный, можно назвать «небезопасным в плане исключений». [7]
Классификация
Стандартная библиотека C++ предоставляет несколько уровней безопасности исключений (в порядке убывания безопасности): [8]
Гарантия отсутствия бросков , также известная как прозрачность отказов : операции гарантированно будут успешными и удовлетворят всем требованиям даже в исключительных ситуациях. Если произойдет исключение, оно будет обработано внутри компании и не будет замечено клиентами.
Сильная безопасность исключений , также известная как семантика фиксации или отката : операции могут завершиться неудачей, но гарантированно не будут иметь побочных эффектов, а исходные значения останутся нетронутыми. [9]
Базовая безопасность исключений : Частичное выполнение неудачных операций может привести к побочным эффектам, но все инварианты сохраняются. Любые сохраненные данные будут содержать допустимые значения, которые могут отличаться от исходных значений. Утечки ресурсов (включая утечки памяти ) обычно исключаются инвариантом, утверждающим, что все ресурсы учитываются и управляются.
Никаких исключений по безопасности : Никаких гарантий не дается.
Обычно для написания надежного кода требуется как минимум базовая безопасность исключений. Более высокие уровни безопасности иногда труднодостижимы и могут повлечь за собой накладные расходы из-за дополнительного копирования. Ключевым механизмом безопасности исключений является finallyпредложение или аналогичный синтаксис обработки исключений , который гарантирует, что определенный код всегда выполняется при выходе из блока, в том числе по исключениям. В нескольких языках есть конструкции, которые упрощают это, в частности, с помощью шаблона dispose , называемого using, withили try-with-resources.
Пример
Рассмотрим интеллектуальный векторный тип, такой как C++ или Java . Когда элемент добавляется в вектор , вектор должен фактически добавить его во внутренний список объектов и обновить поле счетчика, в котором указано, сколько объектов находится в . Также может потребоваться выделить новую память, если существующей емкости недостаточно.std::vectorArrayListxvxv
Исключительные альтернативы безопасности:
Гарантия отсутствия броска
Реализуется путем обеспечения того, что выделение памяти никогда не даст сбоев, или путем определения insertповедения функции при сбое выделения (например, путем возврата функцией логического результата, указывающего, произошла ли вставка).
Сильная безопасность исключений
Реализуется путем выполнения любого необходимого выделения сначала, а затем обмена буферами, если не обнаружено ошибок (идиома копирования и обмена). В этом случае либо вставка в xпроходит vуспешно, либо vостается неизменной, несмотря на ошибку выделения.
Базовая безопасность исключений
Реализовано путем обеспечения того, чтобы поле подсчета гарантированно отражало конечный размер v. Например, если возникает ошибка, insertфункция может полностью освободиться vи сбросить свое поле подсчета на ноль. При сбое ресурсы не утекают, но vстарое значение не сохраняется.
Никаких исключений по безопасности
Ошибка вставки может привести к повреждению содержимого v, неверному значению в поле количества или утечке ресурсов .
Ссылки
^ Крайтон, Алекс (24 июля 2015 г.). «Rust RFC: Стабилизация catch_panic». Язык программирования Rust . Получено 26 мая 2022 г. Код является безопасным в отношении исключений, если он работает правильно, даже если вызываемые им функции выдают исключения.
^ Лау, Рон (10 ноября 2020 г.). «Безопасность исключений в мире JS». Medium .
^ Колвин, Грегори (1994). "Exception Safe Exceptions" (PDF) . Документы Комитета по стандартам C++ . Получено 17 декабря 2021 г. .
^ Абрахамс, Дэвид. «STLport: Обработка исключений». www.stlport.org . Получено 17 декабря 2021 г. .
^ Абрахамс, Дэйв; Колвин, Грег. «Making the C++ Standard Library Exception Safe» (PDF) . Документы Комитета по стандартам C++ . Получено 17 декабря 2021 г. .
^ ab Crichton, Alex (24 июля 2015 г.). "Rust RFC: Stabilize catch_panic". Язык программирования Rust . Получено 26 мая 2022 г.
^ Бьярне Страуструп (1997). Приложение E: Безопасность исключений стандартной библиотеки в "Языке программирования C++" (PDF) (3-е изд.). Addison-Wesley. ISBN0-201-88954-4.
^ Остерн, Мэтт (30 мая 1997 г.). «Политика исключений стандартной библиотеки». Документы Комитета по стандартам C++ . Получено 26 мая 2022 г.
Внешние ссылки
Херб Саттер: Исключительный C++: 47 инженерных головоломок, проблем программирования и их решений, 2000
Джон Калб: Исключительно-безопасное кодирование на языке C++ с презентациями C++Now! 2012 по безопасности исключений.
Сопутствующее обсуждение на Stackoverflow: C++: вы (действительно) пишете безопасный код исключений