Обработка исключений - что происходит после того, как он оставил улов - PullRequest
2 голосов
/ 17 марта 2011

Итак, представьте, что у вас есть исключение, которое вы ловите, а затем в улове вы записываете в файл журнала, что произошло какое-то исключение.Затем вы хотите, чтобы ваша программа продолжалась, поэтому вы должны убедиться, что некоторые инварианты все еще находятся в хорошем состоянии.Однако что на самом деле происходит в системе после того, как исключение было «обработано» перехватчиком?

В этот момент стек был размотан, так как же восстановить его состояние?

Ответы [ 6 ]

5 голосов
/ 17 марта 2011

«Разматывание стека» означает, что все области между throw и соответствующим предложением catch остаются, вызывая деструкторы для всех автоматических объектов в этих областях, почти так же, как области функций остаются при возврате из функция.

Ничего другого "специального" не делается, область действия предложения catch является нормальной областью, и выход из нее ничем не отличается от выхода из области действия предложения else.

Если вам нужно убедиться, что определенные инварианты все еще выполняются, вам необходимо запрограммировать код, изменяя их в поточно-ориентированном режиме. Дэйв Абрахамс написал классику по различным уровням безопасности исключений , вы можете прочитать это. Как правило, вам придется использовать RAII , чтобы быть в безопасности при выдаче исключений.

2 голосов
/ 17 марта 2011

Только объекты, созданные внутри try, будут уничтожены при размотке. Вы должны написать программу таким образом, чтобы в случае возникновения исключения состояние программы оставалось непротиворечивым - это называется безопасность исключений .

C ++ не волнует - он разматывает стек, затем передает управление в соответствующий catch, затем поток управления продолжается в обычном режиме.

2 голосов
/ 17 марта 2011

Вы должны убедиться, что приложение восстановлено в стабильном состоянии после перехвата исключения.Обычно это достигается за счет того, что «забывается» какая-либо операция или изменение (я), вызвавшие исключение, и запускается заново на более высоком уровне.

Это включает в себя гарантию того, что любые ресурсы, выделенные во время цепочки событий, приводящих к исключению, будутправильно выпущен.В C ++ стандартная идиома, гарантирующая, что это RAII .

Обновление

Например, если при обработке запроса на веб-сервере возникает ошибка, он генерируетисключение в некоторой функции более низкого уровня, которая попадает в класс более высокого уровня (возможно, прямо в обработчике запросов верхнего уровня).Обычно лучшее, что можно сделать, - это откатить все сделанные изменения и освободить все ресурсы, выделенные на данный момент, связанные с фактическим запросом, и вернуть соответствующее сообщение об ошибке клиенту.Изменения могут включать в себя транзакции БД, запись в файл и т. Д. - все это необходимо реализовать безопасным образом.Базы данных обычно имеют встроенные транзакции для решения этой проблемы;с другими ресурсами это может быть сложнее.

1 голос
/ 17 марта 2011

Это зависит от приложения. Существует несколько уровней исключительной безопасности. Уровень, который вы описываете, трудно достичь для всего приложения.

Однако некоторые фрагменты кода можно сделать «прозрачными для отказа», используя такие методы, как RAII, и разумно упорядочивая последовательность действий. Я мог бы представить фрагмент кода, запрашивающий несколько URL-адресов для данных, например: когда один URL-адрес будет «выбрасывать», остальные URL-адреса все еще могут быть обработаны. Или это можно повторить ...

0 голосов
/ 17 марта 2011

Не может.Исключения не восстанавливаются в C ++.Ни в большинстве современных языков;некоторые из первых языков, поддерживающих исключения, действительно поддерживали возобновляемые исключения, и обнаружили, что это не очень хорошая идея.

Если вы хотите иметь возможность возобновить работу с определенного момента, вы должны попробоватьпоймать блок там.Если вы просто хотите войти и продолжить, не бросайте исключение в первую очередь.

0 голосов
/ 17 марта 2011

Если у вас есть обработка исключений в каждой функции, которую вы можете возобновить на следующем более высоком уровне, но это довольно сложно, на самом деле я использую исключения главным образом для выявления ошибок как можно ближе к источнику, но не использую их для возобновления выполнения.

если, с другой стороны, есть ошибки, которые можно предсказать, можно разработать схемы для их обработки, но для меня исключения считаются исключениями, поэтому я стараюсь вместо этого изящно завершить работу с хорошим указанием в файле журнала, где это произошло. JM2CW

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...