Re[2]: Legalize throwing destructors! D's scope(failure) and scope(success) in C
От: Evgeny.Panasyuk Россия  
Дата: 28.09.12 11:30
Оценка:
Здравствуйте, UniqueRSDN, Вы писали:

URS>Как быть с ситуациями, когда вызывающий деструктор код рассчитывает на то, что из деструктора не полетит исключение?


Я думал над этим — проблема с транзитивностью действительно есть. Если объект A использует B, который вдруг начал использовать C кидающий исключения из деструктора — то теперь и B и A, и все кто их агрегирует/наследуют, кидают исключения из деструкторов. Причём есть много кода, который не насчитан на кидающие деструкторы.
Похожая проблема существует с мутабельностью.

Сейчас, безопасно(?) можно использовать объект с кидающими деструкторами в блоке кода, но не как член или родитель класса. Например можно кидать исключения в action у scope(success).

URS>Тот же Саттер, рассуждая о безопасности исключений приходит в выводу, что полной безопасности не получится достичь,

URS>не имея гарантии отсутствия исключений для некоторых функций. Деструктор входит в число этих функций.

По поводу кидающих деструкторов, недавно вышла такая статья: Evil, or Just Misunderstood?

URS>Ну или более конкретно, как разрулится такая ситуация:

URS>есть непустой стандартный контейнер объектов. он вышел из скоупа и позвался его деструктор.
URS>он начал звать деструкторы у содержащихся в нем объектов, которые делают важные вещи, правильно распознают
URS>контекст вызова деструктора (по исключению или нет) и если не по исключению, то могут бросить его.
URS>допустим исключение бросил первый же деструктор объекта. деструкторы остальных объектов не позвались.
URS>в результате имеем утечку. или там это как-то хитро разруливается?

Если речь идёт именно о стандартном контейнере, то тут особо ничего не поделаешь.
Если о контейнере вообще — то можно следуя идеологии кидания исключения по возможонсти, поймать первое исключение, остальные проглотить, а потом throw;

При текущем положении дел, кидание исключений из деструкторов опасное занятие, даже если не брать во внимание технические проблемы — большинство кода просто не рассчитано на исключения из деструкторов. Я не агитирую за необдуманное кидание исключений из деструкторов налево и направо (несмотря на название топика )
Но в то же время, помимо непосредственно деструкции и освобождения ресурсов, на деструкторы навешиваются разного рода отложенные действия, например тот же flush, которые могут фэйлится. Проглатывание всех этих фэйлов по-умолчанию — решение далёкое от идеала.

Например, текущая ситуация по-умолчанию(без явных вызовов flush/close/etc, без логирования фэйла(которое может также сфэйлится)):

1. Первый деструктор — фейл, no action
2. Второй деструктор — фейл, no action
3. Обработка молча завершена

или с киданием исключения по возможности:

1. Первый деструктор — фейл, кидает исключение
2. Второй деструктор во время раскрутки — фэйл, кидать нельзя
3. catch первого исключения выше по call-stack'у, в месте ответственном за их обработку
4. информирование пользователя
5. пользователь устраняет причины, и запускает обработку заново
6. Первый деструктор — success
7. Второй деструктор — фэйл (а может и не фэйл, если зависело от первого), кидает исключение
... пользователь узнаёт об этом, исправляет и запускает заново.
Ведь вполне возможный сценарий.

Что лучше?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.