Re[6]: Что делать с проблемами в деструкторе?
От: jahr  
Дата: 17.11.15 14:51
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>Застрелиться aka terminate(). Есть другие варианты?


Как раз другие варианты и хотелось бы найти.)
Re[7]: Что делать с проблемами в деструкторе?
От: landerhigh Пират  
Дата: 17.11.15 14:59
Оценка: +1
Здравствуйте, jahr, Вы писали:

J>Как раз другие варианты и хотелось бы найти.)

Ну а какие еще могут быть варианты, если система возвращает ошибку, которую проигнорировать нельзя, а обработать невозможно?
www.blinnov.com
Re[3]: Коды возврата как в Си
От: Qbit86 Кипр
Дата: 17.11.15 18:46
Оценка:
Здравствуйте, jahr, Вы писали:

Q>>Запись в файл делай в отдельном методе Save(), или Flush(), или Close(), etc. В коде явно вызывай этот метод (потенциально бросающий исключение) в нормальном потоке выполнения, не полагаясь на деструктор.

Q>>В деструкторе тоже можешь попытаться вызвать этот метод или его содержимое (проверив, что объект «грязный» и сохранение действительно нужно, и не было ранее сделано вызовом Save()), но только обеспечив непросачивание исключений из этого вызова. Но лишь как last resort, не полагаясь на это при нормальном использовании класса.

J>Тогда мне придется каждое использование этого класса обкладывать try'ем, в catch'е которого вызывать этот метод Save, использование класса станет мучением, эти перехваты везде писать будет лениво, я начну это пропускать, начнутся ошибки и понесется.) Тогда уж проще вообще отказаться от исключений и работать только на кодах возврата как в С.)


Но методы flush и close у стандартного fstream примерно так и работают. fstream делает попытку «сохранить» (сбросить буффер) в деструкторе, но никак не уведомляют в случае фейла. При ручном закрытии успешность close'а можно опросить (badbit, failbit).
Глаза у меня добрые, но рубашка — смирительная!
Re[4]: Что делать с проблемами в деструкторе?
От: Vain Россия google.ru
Дата: 17.11.15 19:43
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Тяжёлые операции в конструкторе — без проблем.

ага, знаем мы эти "без проблем" в случае статиков и глобалов..
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[8]: Что делать с проблемами в деструкторе?
От: Vain Россия google.ru
Дата: 17.11.15 19:45
Оценка:
Здравствуйте, landerhigh, Вы писали:

J>>Как раз другие варианты и хотелось бы найти.)

L>Ну а какие еще могут быть варианты, если система возвращает ошибку, которую проигнорировать нельзя, а обработать невозможно?
почему это?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[5]: Что делать с проблемами в деструкторе?
От: landerhigh Пират  
Дата: 17.11.15 21:21
Оценка: +2
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Деструкторы могли бы нормально кидать исключения, например если бы многократные исключения аккумулировались в одно.

EP>В случаях же где из-за алгоритмических особенностей нужен не кидающий деструткор — использовали бы noexcept.

EP>Даже была статья на эту тему — "Destructors That Throw: Evil, or Just Misunderstood? — Jon Kalb and Dave Abrahams" (оригинальный сайт выпилен, а копию/кэш я сходу не нашёл). Там была фраза, что-то в духе: "делать std::terminate в таких случаях это слишком драконовские меры".


Почитал. Принципиальной невозможности аккумулировать исключения имхо особенно нет. Но у меня другой вопрос — а что с объектом-то? Вот выкинул он исключение на полпути деструктора. И стал зомби. Вернуть к жизни его нельзя. Добить? Как? Разрешать рекуррентный вызов деструктора, чтобы наверняка добить? Так это ничем не отличается от цепочки cleanup() — delete.

Или принять ограничения, что исключение в деструкторе — чисто информационное и объект, выбросивший его, гаратированно убит?
www.blinnov.com
Re[9]: Что делать с проблемами в деструкторе?
От: landerhigh Пират  
Дата: 17.11.15 21:33
Оценка:
Здравствуйте, Vain, Вы писали:

V>Здравствуйте, landerhigh, Вы писали:


J>>>Как раз другие варианты и хотелось бы найти.)

L>>Ну а какие еще могут быть варианты, если система возвращает ошибку, которую проигнорировать нельзя, а обработать невозможно?
V>почему это?

У меня есть смутное подозрение, что этот разговор опять смещается в сторону сферического случая в вакууме с обработкой ошибки от функции закрытия файла.
www.blinnov.com
Re: Что делать с проблемами в деструкторе?
От: AlexRK  
Дата: 17.11.15 21:36
Оценка: +1
Здравствуйте, jahr, Вы писали:

J>Много лет не могу для себя решить, как правильно себя вести при возникновении каких-то проблем во время выполнения деструктора.


J>Например, для конкретики, есть у нас класс, в конструкторе читает данные из файла, в деструкторе — записывает модифицированные данные обратно в файл. Делать все это хочется именно в конструкторе и деструкторе, чтобы эти действия выполнялись автоматически, при возникновении исключений при выполнении промежуточных действий — они правильно обрабатывались и т.п., как мне кажется, это стандартная более-менее практика.


J>И вот что делать, если в деструкторе не удалось выполнить запись в файл? Исключение кидать нельзя, игнорировать ошибку как-то неправильно, запись в лог — какое-то костыльное решение, не всегда уместно.

J>Не выполнять в деструкторе никаких сложных действий? Но как же тогда концепция автоматического захвата-освобождения ресурсов в конструкторе-деструкторе, она вроде как считается правильной, и мой пример работы с файлом в нее укладывается, насколько я ее понимаю.

J>В общем, буду признателен, если вы поделитесь своими способами реализовать описанный в примере сценарий работы идеологически правильным способом.)


Нормального — идеологически — варианта нет.
Можно использовать (как большинство и делает) "грязный" вариант с глушением ошибок в деструкторе, и надеяться, что ошибка не произойдет. В принципе, в подавляющем большинстве случаев она и не происходит.
Если же нужна обработка, то только отдельный метод для финализации. Более многословно, но такой подход и более корректен.
Re[10]: Что делать с проблемами в деструкторе?
От: Vain Россия google.ru
Дата: 17.11.15 22:23
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>>>Ну а какие еще могут быть варианты, если система возвращает ошибку, которую проигнорировать нельзя, а обработать невозможно?

V>>почему это?
L>У меня есть смутное подозрение, что этот разговор опять смещается в сторону сферического случая в вакууме с обработкой ошибки от функции закрытия файла.
я не понял почему ошибку проигнорировать нельзя? кто сказал что нельзя?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[3]: Проблемы в деструкторе
От: smeeld  
Дата: 17.11.15 22:33
Оценка:
Здравствуйте, jahr, Вы писали:

J>Тогда мне придется каждое использование этого класса обкладывать try'ем, в catch'е которого вызывать этот метод Save, использование класса станет мучением, эти перехваты везде писать будет лениво, я начну это пропускать, начнутся ошибки и понесется.) Тогда уж проще вообще отказаться от исключений и работать только на кодах возврата как в С.)


Учитывая, что обработка в catch это очень затратная процедура, то проверка в кодах возрата,
как в Си, будет явно производительней, за исключением случаев, когда проверяемая функция вызывается
в циклах с миллионами итераций.
Re[11]: Что делать с проблемами в деструкторе?
От: landerhigh Пират  
Дата: 17.11.15 22:47
Оценка:
Здравствуйте, Vain, Вы писали:

L>>>>Ну а какие еще могут быть варианты, если система возвращает ошибку, которую проигнорировать нельзя, а обработать невозможно?

V>>>почему это?
L>>У меня есть смутное подозрение, что этот разговор опять смещается в сторону сферического случая в вакууме с обработкой ошибки от функции закрытия файла.
V>я не понял почему ошибку проигнорировать нельзя? кто сказал что нельзя?

Ключевое слово выделено вверху. Это то, о чем ТС спрашивал.
www.blinnov.com
Re[12]: Что делать с проблемами в деструкторе?
От: Vain Россия google.ru
Дата: 17.11.15 22:58
Оценка:
Здравствуйте, landerhigh, Вы писали:

V>>я не понял почему ошибку проигнорировать нельзя? кто сказал что нельзя?

L>Ключевое слово выделено вверху. Это то, о чем ТС спрашивал.
система вроде вообще не может вернуть ошибку, которую нельзя проигнорировать, для чего тогда хуки?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[13]: Что делать с проблемами в деструкторе?
От: landerhigh Пират  
Дата: 17.11.15 22:59
Оценка:
Здравствуйте, Vain, Вы писали:

L>>Ключевое слово выделено вверху. Это то, о чем ТС спрашивал.

V>система вроде вообще не может вернуть ошибку, которую нельзя проигнорировать, для чего тогда хуки?

Тема вообще не об этом. А о деструкторах.
www.blinnov.com
Re: Что делать с проблемами в деструкторе?
От: CEMb  
Дата: 18.11.15 04:27
Оценка:
Здравствуйте, jahr, Вы писали:

J>И вот что делать, если в деструкторе не удалось выполнить запись в файл? Исключение кидать нельзя, игнорировать ошибку как-то неправильно, запись в лог — какое-то костыльное решение, не всегда уместно.

J>Не выполнять в деструкторе никаких сложных действий? Но как же тогда концепция автоматического захвата-освобождения ресурсов в конструкторе-деструкторе, она вроде как считается правильной, и мой пример работы с файлом в нее укладывается, насколько я ее понимаю.

А можешь расписать алгоритм, как в идеале ты это видишь?

У меня для приближения к идеалу тут 2 перпендикулярных пункта:
1. вынести всю работу с файлом в отдельный класс, который и будет заниматься разными ситуациями в своём деструкторе. Это проблему не решит, но наведёт больше порядка и поделит проблему надвое.
2. если нужна ситуация, которую надо обработать _не_ в конструкторе/деструкторе, при этом хочется использовать этот механизм, то я бы завёл некий класс-няньку, который в конструкторе создавал бы объект моего класса, или принимал ссылку на него и тогда ничего не делал. А в деструкторе звал бы release или что там нужно для освобождения. При этом, да, нужно где-то хранить ещё указатель на сам объект нашего класса(можно завести пул объектов, куда смотрят няньки). В результате:
2.1. в нянька-конструкторе, если что-то пошло не так, мы просто не получим наш объект. Всё ок.
2.2. в нянька-деструкторе, если что-то пошло не так, объект-нянька погибнет, но сможет сообщить, что освобождение ресурсов не завершено, или просто сбросит свой дочерний объект в пул. Указатель на наш объект остался жив, мы можем создать новый объект-няньку, которому передать ссылку на наш объект и повторить пункт 2.2.

коряво, да, но в _нашем_ классе проблема решена но это всё, imho, "вам шашечки или ехать?", кому что больше хочется.

если конкретно про файл, то мне кажется, ситуацию с завершением можно решить в деструкторе нормально, т.е. записать в файл, если не записалось, записать в другой, или в лог, или окно показать или ещё что, в зависимости от ситуации и того, что хотел автор.
Re[2]: Что делать с проблемами в деструкторе?
От: Vlad_SP  
Дата: 18.11.15 07:54
Оценка: +1
Здравствуйте, CEMb,

CEM>2.2. [.....] Указатель на наш объект остался жив, мы можем создать новый объект-няньку, которому передать ссылку на наш объект и повторить пункт 2.2.


Мне представляется, что тут самой главной проблемой будет — как корректно "добить" наш объект, учитывая, что он уже частично "мертвый", частично еще "живой"? ("А что недострелили — так я не виноват." (с))
Re: Что делать с проблемами в деструкторе?
От: T4r4sB Россия  
Дата: 18.11.15 11:25
Оценка: +1
В деструкторе записывать успешность результата во внешнюю переменную (ссылка на которую даётся в конструкторе). Потом проверять эту переменную.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[3]: Что делать с проблемами в деструкторе?
От: CEMb  
Дата: 18.11.15 11:40
Оценка:
Здравствуйте, Vlad_SP, Вы писали:

CEM>>2.2. [.....] Указатель на наш объект остался жив, мы можем создать новый объект-няньку, которому передать ссылку на наш объект и повторить пункт 2.2.


V_S>Мне представляется, что тут самой главной проблемой будет — как корректно "добить" наш объект, учитывая, что он уже частично "мертвый", частично еще "живой"? ("А что недострелили — так я не виноват." (с))


Ага, вот потому и пункт 1 — минимизировать классы таких объектов. Т.е. или жив или мёртв(отсутствует в пуле). Если жив, убивается ровно одним однозначным способом. К примеру, файл полностью записан и закрыт.
Re[4]: Что делать с проблемами в деструкторе?
От: Vlad_SP  
Дата: 18.11.15 12:01
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM> К примеру, файл полностью записан и закрыт.


В файл записалась только половина данных, дальше кончилось место на диске.
На сервер в Тимбукту передана только половина данных, дальше пьяный экскаваторщик Вася в Мухосранске порвал магистральный кабель.
И так далее....
Re[5]: Что делать с проблемами в деструкторе?
От: landerhigh Пират  
Дата: 18.11.15 12:10
Оценка:
Здравствуйте, Vlad_SP, Вы писали:

V_S>В файл записалась только половина данных, дальше кончилось место на диске.

V_S>На сервер в Тимбукту передана только половина данных, дальше пьяный экскаваторщик Вася в Мухосранске порвал магистральный кабель.
V_S>И так далее....

Всем такие события поздновато разруливать в деструкторе.
В принципе можно, но под этим деструктором должна быть еще куча уровней, которые умеют это разруливать сами.
www.blinnov.com
Re[6]: Что делать с проблемами в деструкторе?
От: Evgeny.Panasyuk Россия  
Дата: 18.11.15 12:45
Оценка:
Здравствуйте, landerhigh, Вы писали:

EP>>Даже была статья на эту тему — "Destructors That Throw: Evil, or Just Misunderstood? — Jon Kalb and Dave Abrahams" (оригинальный сайт выпилен, а копию/кэш я сходу не нашёл). Там была фраза, что-то в духе: "делать std::terminate в таких случаях это слишком драконовские меры".

L>Почитал. Принципиальной невозможности аккумулировать исключения имхо особенно нет.

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

L>Но у меня другой вопрос — а что с объектом-то? Вот выкинул он исключение на полпути деструктора. И стал зомби. Вернуть к жизни его нельзя. Добить? Как? Разрешать рекуррентный вызов деструктора, чтобы наверняка добить? Так это ничем не отличается от цепочки cleanup() — delete.

L>Или принять ограничения, что исключение в деструкторе — чисто информационное и объект, выбросивший его, гаратированно убит?

Например в само исключение можно запаковывать все внутренности объекта. То есть например file handle будет внутри объекта исключения.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.