etc:users:yuri_v_katkov:exception-safety
Table of Contents
Безопасный по отношению к исключениям код
Безопасный код в смысле исключений - это код, который при выбрасывании функцией исключения работает следующим образом
- из него не течет память,
- он не завершается аварийно, если это не было предусмотрено специально,
- состояние всех объектов согласовано и известно (структуры данных не повреждены),
- еще?
Нейтральный по отношению к исключениям код - это код, передающий обработку исключения вызывающей функции.
Категории безопасности
- базовая гарантия - отсутствуют утечки памяти, даже если исключения выбрасываются.
- строгая гарантия - если операция прекращается из-за генерации исключения, состояние программы остаётся неизменным
- гарантия отсутствия исключений - исключения не выбрасываются.
Напоминание-ликбез
- исключение - это такой объект любого типа,
- операторы try, catch, throw, catch(…)
- перезапуск исключения
- спецификация исключений. Нужно ли их писать?
- terminate(), unexpected()
Требования к функциям
Конструктор
- должен быть нейтральным
- может генерировать любые исключения
- почему после исключения в конструкторе мы не говорим о несогласованном состоянии объекта?
Деструктор и операторы delete
Деструктор не должен генерировать исключения. Этому есть несколько причин:
- если мы сделаем массив объектов T, где ~T() может генерировать исключения, то что случится, когда при удалении этого массива один из деструкторов выкинет исключение? Ответ такой: память потечет!
class Anarc { ~Anarc() { throw std::exception; } } int main() { try { Anarc* mas = new Anarc[3000]; delete[] mas; } catch() {} ... // какой-то код }
- а главное, в Стандарте сказано, что любой код, который веделяет или удаляет массив объектов, деструкторы которых генерируют исключения приводит к undefined behavior
Хорошие практики
- выполнять сначала код, который может выкинуть исключения и только потом менять состояние объекта
для этого можно использовать вспомогательные функции, которые выполняют все операции, способные вызвать исключения; перехватывают их и передают исключения вызывающей функции
- использовать идиому RAII для управления ресурсами: каждым ресурсом владеет объект. В деструкторе этого объекта происходит освобождение ресурса.
- использовать функции, не генерирующие исключений (например, swap())
Ссылки
etc/users/yuri_v_katkov/exception-safety.txt · Last modified: 2016/08/08 20:53 by kel