Советы от the ScopeGuard article был
В области исключений, то важно, чтобы вы не можете ничего сделать, если ваш «отменить/восстановить» действие не удается. Вы пытаетесь выполнить операцию отмены, и вы двигаетесь независимо от того, успешно ли выполняется операция отмены или нет.
Это может показаться сумасшедшим, но учтите:
- мне удается запустить из памяти и получить
std::bad_alloc
исключение
- Моя очистка код регистрирует ошибку
- К сожалению, запись (возможно, диск заполнен) и пытается выбросить исключение
Можно ли отменить запись журнала? Должен ли я попробовать?
Когда вы выбрали исключение, все, что вы действительно знаете, это то, что программа находится в недопустимом состоянии. Вы не должны удивляться, что некоторые невозможные вещи оказываются возможными в конце концов.Лично я видел гораздо больше случаев, когда советы Александрадреску имеют наибольший смысл, чем в противном случае: попытайтесь очистить, но признайте, что первое исключение означает, что вещи уже находятся в недопустимом состоянии, поэтому дополнительные сбои - особенно сбои, вызванные первая проблема («каскад ошибок») - не должно быть неожиданностью. И попытка справиться с ними не закончится хорошо.
я, вероятно, следует отметить, что Cap'n Прото делает именно то, что вы предложили:
Когда Cap'n Прото код может бросить исключение из деструктора, он сначала проверяет std::uncaught_exception()
, чтобы обеспечить что это безопасно. Если другое исключение уже активно, новое исключение считается побочным эффектом основного исключения и либо молчаливо проглатывается, либо сообщается на боковом канале.
Но, как сказал Якк, деструкторы стали nothrow(true)
по умолчанию в C++ 11. Это означает, что если вы хотите это сделать, вы должны быть уверены, что в C++ 11 и более поздних версиях вы помечаете деструктор как nothrow(false)
. В противном случае исключение из деструктора исключает программу, даже если в полете нет другого исключения. И обратите внимание: «Если другое исключение уже активно, новое исключение считается побочным эффектом основного исключения и либо молчаливо проглатывается, либо сообщается на боковом канале».
Это на самом деле не отличается от более общего случая «как предотвратить прерывание, если у меня есть класс, деструктор которого может бросить». Я не думаю, что есть хороший ответ, кроме как «деструкторы должны * не бросать». – sfjac
Без деструктора, выполняющего некоторую работу, нет RAII. Я очень надеюсь, что есть что-то, что можно было бы сделать. Скажите что-то, основанное на std :: uncaught_exception, где вы можете обнаружить, если есть, например, какое-то исключение. – gsf