Безопасный по отношению к исключениям код
Безопасный код в смысле исключений - это код, который при выбрасывании функцией исключения работает следующим образом
из него не течет память,
он не завершается аварийно, если это не было предусмотрено специально,
состояние всех объектов согласовано и известно (структуры данных не повреждены),
еще?
Нейтральный по отношению к исключениям код - это код, передающий обработку исключения вызывающей функции.
Категории безопасности
базовая гарантия - отсутствуют утечки памяти, даже если исключения выбрасываются.
строгая гарантия - если операция прекращается из-за генерации исключения, состояние программы остаётся неизменным
гарантия отсутствия исключений - исключения не выбрасываются.
Напоминание-ликбез
исключение - это такой объект любого типа,
операторы 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())
Ссылки