Здравствуйте, IB, Вы писали:
C>>Неверно. Повторный выброс исключения в C#/Java затирает предидущее исключение. IB>Не всегда. Справедливости ради, надо заметить, что есть и InnerException и просто throw без параметров, что в том или ином виде делает доступным оригинальное исключение выше по стеку.
Ну так и в С++ можно извратиться. Например, вручную сделать exception chaining.
Sapienti sat!
Re[21]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, Cyberax, Вы писали:
D>>Просто прелестно. 2008 год на дворе, а у нас глобальные флаги и GetError() во всей своей красе... А люди-то парились, исключения городили... А ну нафиг всё, ведь есть флаги!!! C>Ну флаги. И что дальше? Что делать, если они лучше всего подходят для решения проблемы...
Лучше всего подходят исключения, просто не надо пихать очистку нетривиальных ресурсов в деструкторы.
D>>Разумеется! Я совершенно с Вами согласен. И именно поэтому в нормальных языках типа C# сделаны try/finally/using/IDisposable и GC впридачу. Бо не надо мешать задачу управления циклом жизни объекта в одну кучу с задачей управления памятью, занимаемой этим самым объектом. C>try..finally — это кривой аналог деструктора.
Чушь. Я уже перечислял свойства (они же, по-совместительству, и основные проблемы) деструкторов. try/finally/using/IDisposable ничем из этого раздела не болеют.
D>>Тогда Вы, наверняка, сумеете ответить на мой вопрос о rationale положений стандарта о вызове terminate(), в случае исключения при развёртке стека. Или не сможете ? C>Смогу. Оно нужно для гарантии того, что изначальное исключение не будет молчаливо затёрто.
Тоже не годится. Насколько я понимаю механизм реализации, исключения создаются на стеке аналогично обычным автоматическим объектам, и никто никого не затирает, разумеется. Например, при развёртке стека нет никаких проблем бросать исключения внутри деструкторов, в том числе и из функций вызываемых ими, и с какой-угодно глубины. Лишь бы ловились обязательно, не вылезая за границу. Так что в случае разрешения исключений из деструкторов при развёртке стека, вся их цепочка всегда наличествует.
Re[21]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, eao197, Вы писали:
D>>Просто прелестно. 2008 год на дворе, а у нас глобальные флаги и GetError() во всей своей красе... А люди-то парились, исключения городили... А ну нафиг всё, ведь есть флаги!!!
E>Есть, по крайней мере, одна хорошая C++ библиотека,
Ну так назовите её, поглядим.
E>которая использует uncaught_exception в деструкторах для того, чтобы принять решение о том, можно ли порождать исключение или нет, если очистка ресурсов идет с ошибками. Тоже, ведь, на флагах работа построена.
Не вижу в этом ничего хорошего. Типичный "Костылиус Вульгарис".
Re[22]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, drol, Вы писали:
C>>Ну флаги. И что дальше? Что делать, если они лучше всего подходят для решения проблемы... D>Лучше всего подходят исключения, просто не надо пихать очистку нетривиальных ресурсов в деструкторы.
Да, или такой вариант тоже.
C>>try..finally — это кривой аналог деструктора. D>Чушь. Я уже перечислял свойства (они же, по-совместительству, и основные проблемы) деструкторов. try/finally/using/IDisposable ничем из этого раздела не болеют.
Они болеют ну ровно теми же проблемами. Просто решаются они по-другому. В Java/.NET вместо просто выбрали более ненадёжное решение.
C>>Смогу. Оно нужно для гарантии того, что изначальное исключение не будет молчаливо затёрто. D>Тоже не годится. Насколько я понимаю механизм реализации, исключения создаются на стеке аналогично обычным автоматическим объектам, и никто никого не затирает, разумеется.
Смотри, пример из моего собеседования:
class Test
{
static void doSomething() throws Exception
{
FileInputStream fl=null;
try {
fl=new FileInputStream(“c:\\ЭтогоФайлаНет”); //Кинет IOException
} catch(Throwable t) {
throw new RuntimeException(“Файл не может быть открыт!”);
} finally {
fl.close();
}
}
public static void main(String []args)
{
try { doSomething();} catch(Throwable t) {
System.out.println(t.getClass().getName());
}
}
}
Что будет напечатано в итоге?
Sapienti sat!
Re[19]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, nikov, Вы писали:
N>Покажи код, если можно.
Код чего? =) Вызова throw или помещения оригинального исключения внутри catch в InnerException?
Я думаю ты лучше меня знаешь, как это работет.
Мы уже победили, просто это еще не так заметно...
Re[19]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, Cyberax, Вы писали:
C>Ну так и в С++ можно извратиться. Например, вручную сделать exception chaining.
Да байта ради. =) Просто ты утверждал, что "Повторный выброс исключения в C#/Java затирает предидущее исключение", что не совсем верно. Более того, в отличии от C++ это делается не "в ручную", а совершенно стандартным способом, через нарошно предназначенное для этого технологическое отверстие.
Мы уже победили, просто это еще не так заметно...
Re[20]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, IB, Вы писали:
C>>Ну так и в С++ можно извратиться. Например, вручную сделать exception chaining. IB>Да байта ради. =) Просто ты утверждал, что "Повторный выброс исключения в C#/Java затирает предидущее исключение", что не совсем верно.
Нет, это верно. Но с примечанием — можно делать вложенные исключения.
Sapienti sat!
Re[21]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, Cyberax, Вы писали:
C>Нет, это верно.
throw без параметров за повторный выброс не считается?
C>Но с примечанием — можно делать вложенные исключения.
Довольно существенное замечание, не находишь?
Мы уже победили, просто это еще не так заметно...
Re[22]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, IB, Вы писали:
C>>Нет, это верно. IB>throw без параметров за повторный выброс не считается?
Ну выбросит оно предидущее исключение, и что? В С++ так же можно.
C>>Но с примечанием — можно делать вложенные исключения. IB>Довольно существенное замечание, не находишь?
Не совсем согласен, что оно существенное.
Sapienti sat!
Re[23]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, Cyberax, Вы писали:
C>>>Ну флаги. И что дальше? Что делать, если они лучше всего подходят для решения проблемы... D>>Лучше всего подходят исключения, просто не надо пихать очистку нетривиальных ресурсов в деструкторы. C>Да, или такой вариант тоже.
Ну наконец-то...
C>>>try..finally — это кривой аналог деструктора. D>>Чушь. Я уже перечислял свойства (они же, по-совместительству, и основные проблемы) деструкторов. try/finally/using/IDisposable ничем из этого раздела не болеют. C>Они болеют ну ровно теми же проблемами. Просто решаются они по-другому.
Опять чушь. Теми же проблемами болеют finalizer'ы, а с try/finally/using/IDisposable всё в порядке.
C>В Java/.NET вместо просто выбрали более ненадёжное решение.
Наоборот. Куда как более надёжное. И чем terminate(), и чем молчание ягнят при отказе очистки в деструкторе.
C>>>Смогу. Оно нужно для гарантии того, что изначальное исключение не будет молчаливо затёрто. D>>Тоже не годится. Насколько я понимаю механизм реализации, исключения создаются на стеке аналогично обычным автоматическим объектам, и никто никого не затирает, разумеется.
C>Смотри, пример из моего собеседования:
Причём здесь Java-то ??? Речь о C++, и таки ещё раз повторю: все исключения на стеке и доступны.
C>Что будет напечатано в итоге?
Очевидно, что скорее всего java.lang.NullPointerException
*Это не касаясь вопроса, что за такой код лично я бы сразу расстреливал
Ну так и что Вы хотели показать этим примером ? Что кто-то "съел" исключение ? Да, совершенно верно, съел. И это были Вы сами, когда не стали обрабатывать возможность исключения в finally-блоке.
В Java/C# нет никакого "затирания" исключений. Бо некому затирать. Функция может либо бросить исключение, либо нормально отработать. И всё. Любой вызов чего угодно всегда можно обложить try/catch и обработать это самое единственное исключение как душе будет угодно.
Это в C++ может возникнуть целая цепочка исключений из функции, бо при раскрутке стека деструкторы вызываются вне нормального контекста исполнения. И в функции невозможно написать try/catch ловящий исключения бросаемые только деструктором конкретного автоматического объекта. Тогда как в Java/C# такого понятия как "раскрутка стека" вообще не существует.
Re[24]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, drol, Вы писали:
C>>Они болеют ну ровно теми же проблемами. Просто решаются они по-другому. D>Опять чушь. Теми же проблемами болеют finalizer'ы, а с try/finally/using/IDisposable всё в порядке.
Нет. Проблемы те же.
C>>В Java/.NET вместо просто выбрали более ненадёжное решение. D>Наоборот. Куда как более надёжное. И чем terminate(), и чем молчание ягнят при отказе очистки в деструкторе.
Нет. В Java/.NET мы без следов теряем изначальное исключение.
C>>Смотри, пример из моего собеседования: D>Причём здесь Java-то ??? Речь о C++, и таки ещё раз повторю: все исключения на стеке и доступны.
Я говорю про альтернативное решение — перезапись исключения.
C>>Что будет напечатано в итоге? D>Очевидно, что скорее всего java.lang.NullPointerException
Да.
D>Ну так и что Вы хотели показать этим примером ? Что кто-то "съел" исключение ? Да, совершенно верно, съел. И это были Вы сами, когда не стали обрабатывать возможность исключения в finally-блоке.
Неправда. Мы в блоке finally кидаем исключение, которое ЗАМЕНЯЕТ выброщенный RuntimeException. Всё. От RuntimeException у нас в вызывающей функции следов не осталось.
В C++ в этом случае для надёжности решили делать std::terminate.
D>В Java/C# нет никакого "затирания" исключений. Бо некому затирать.
Есть. См. мой пример.
D>Тогда как в Java/C# такого понятия как "раскрутка стека" вообще не существует.
Существует. Выполнение блоков finally — ну абсолютно то же самое. Оно даже внутри реализовано так же.
Sapienti sat!
Re[25]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, Cyberax, Вы писали:
C>>>Они болеют ну ровно теми же проблемами. Просто решаются они по-другому. D>>Опять чушь. Теми же проблемами болеют finalizer'ы, а с try/finally/using/IDisposable всё в порядке. C>Нет. Проблемы те же.
"Я всё сказал" (с) не мой
Я не знаю как объяснить проще и доступнее. Если Вы не понимаете такой элементарщины, то я Вам ничем помочь больше не могу...
C>>>В Java/.NET вместо просто выбрали более ненадёжное решение. D>>Наоборот. Куда как более надёжное. И чем terminate(), и чем молчание ягнят при отказе очистки в деструкторе. C>Нет. В Java/.NET мы без следов теряем изначальное исключение.
Наглая ложь. В Java/C# ничего не теряется. Любое исключение пробрасываемое через функцию может быть поймано и обработано.
C>>>Смотри, пример из моего собеседования: D>>Причём здесь Java-то ??? Речь о C++, и таки ещё раз повторю: все исключения на стеке и доступны. C>Я говорю про альтернативное решение — перезапись исключения.
А я говорю про реальное решение. Которое необходимо, бо исключения в деструкторах при раскрутке стека, согласно стандарту, должны нормально обрабатываться независимо от глубины вложенности. Так что не в перезаписи дело, она не является необходимой.
D>>Ну так и что Вы хотели показать этим примером ? Что кто-то "съел" исключение ? Да, совершенно верно, съел. И это были Вы сами, когда не стали обрабатывать возможность исключения в finally-блоке. C>Неправда. Мы в блоке finally кидаем исключение, которое ЗАМЕНЯЕТ выброщенный RuntimeException.
Чушь. Никто ничего не заменяет. try/finally это по-факту синтаксический сахар на базе try/catch/throw, то есть обычной обработки исключения с его возможным "пробросом". Если Вы обложите try/catch'ем содержимое finally-блока, то на выходе получите свой любимый RuntimeException. А вот теперь попробуйте сделать то же самое с вызовом деструктора автоматического объекта в C++...
C>В C++ в этом случае для надёжности решили делать std::terminate.
Ну всё, приехали, terminate==надёжность... Даже не знаю что и сказать-то. Разве что порекомендовать почитать БСЭ на тему... раз эдак семь.
*Только не забудьте перед этим ещё и читать научиться...
D>>В Java/C# нет никакого "затирания" исключений. Бо некому затирать. C>Есть. См. мой пример.
Вот именно, смотрите собственный пример.
D>>Тогда как в Java/C# такого понятия как "раскрутка стека" вообще не существует. C>Существует. Выполнение блоков finally — ну абсолютно то же самое. Оно даже внутри реализовано так же.
См. выше. try/finally в этом моменте реализован через try/catch. Никакой раскрутки здесь нет.
Здравствуйте, SE, Вы писали: SE>Может быть уважаемый Sinclair вместо раздачи минусов направо и налево объяснит, с чем он в примере не согласен, и каким образом можно восстановить цепочку исключений случившихся в using после исключения в методе Dispose?
Я привел пример. http://rsdn.ru/forum/message/3050988.1.aspx
Здравствуйте, Sinclair, Вы писали:
S>Очень простой в этом смысл: сообщаем вызывающему, что детерминистическая финализация не удалась. S>К примеру, при закрытии файла не удается сделать flush по причине отсутствия доступа к устройству. S>В отличие от C++, имеем детерминированный способ обработать эту ситуацию. К примеру, попробовать открыть файл на другом устройстве и повторить операцию записи, которая была прервана исключением.
Гмм. Я правильно понял:
1. Flush из деструктора не прошел по причине отсутсвия файла
2. Бросили исключение из деструктора
3. Поймали исключение (где-то)
4. Открыли другой файл и сделали в него Flush
5. Все счастливы ?
Re[26]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, drol, Вы писали:
D>Наглая ложь. В Java/C# ничего не теряется. Любое исключение пробрасываемое через функцию может быть поймано и обработано.
Давайте только не вилять и не давать словам собеседника свой смысл, а потом опровергать. А то это уже не диалог.
Это аналогично спору "исключения или возвращаемые значения?"
— Исключение нельзя не обработать
— Чушь, не напишем try-catch и всё
— Возвращаемые значение могут быть не проверены
— Наглая ложь. Возвращаемые значения не теряются. Любое возвращаемое значение можно проверить и обработать.
Исключения отличаются тем, что их придётся обработать. И вы это прекрасно понимаете. Только для спора, конечно, можно и подменить понятия, да? Тут же вам говорят, что возможна ситуация, когда исключение остается необработанным само по себе, без специальных замашек со стороны программиста в виде catch {} (catch ( ... ) {})
Re[17]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, Gluk_Kazan, Вы писали:
G_K>1. Flush из деструктора не прошел по причине отсутсвия файла G_K>2. Бросили исключение из деструктора G_K>3. Поймали исключение (где-то) G_K>4. Открыли другой файл и сделали в него Flush G_K>5. Все счастливы ?
Примерно так. Вот более подробный пример: http://rsdn.ru/forum/message/3051012.1.aspx
Тогда какие отличия? Только в том, что в шарпе долетает последнее исключение из всей цепочки, а в Си++ — первое. Но во-первых в ветке else можно куда-то что-то записать, а во-вторых, из двух исключений, одно из которых вызвало вереницу обвалов, а второе полетело в самом конце из-за того, что файл не закрылся, лично я выбрал бы первое. Но это отдельная тема для дискуссий. В идеале хорошо было бы получить все исключения.
И не пойму, что мешало в шарпе сделать так, чтобы при броске нового исключения предыдущее не затиралось, а записывалось новому в Inner автоматически?
Re[28]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, SE, Вы писали: SE>>Может быть уважаемый Sinclair вместо раздачи минусов направо и налево объяснит, с чем он в примере не согласен, и каким образом можно восстановить цепочку исключений случившихся в using после исключения в методе Dispose? S>Я привел пример. http://rsdn.ru/forum/message/3050988.1.aspx
Ну, это отличный пример. Тут вот какая проблема. Помимо тех исключений которые Вы кидаете и ловите в блоках try/catch существуют еще "неудобные" исключения, связанные с нехваткой памяти, шатдауном системы и даже нарушениями выполения кода внутри CLR. И это не фантастика, такие эксепшены ловил каждый кто пробовал писать/генерировать непосредственно IL код.
Их нельзя "проглатывать", их надо пробрасывать наверх.
Как Вы конечно знаете (но остальной аудитории может быть интересно) using — это фактически try/catch c вызовом Dispose в finally.
И вот Вы пробрасываете наверх эти пакостные исключения, чтоб словить их на самом верху и просто закрыть программу с наименьшими потерями для пользователя, а тем временем Dispose из-за указаных причин тоже кидает эксепшен, и как показазано в моем примере, исходный эксепшен, скажем о нарушении работы стека CLR гасится, а остается безобидный об ошибке освобождения ресурса.
Re[22]: Зачем нужен сборщик мусора? Как жить без деструкторо
Здравствуйте, drol, Вы писали:
E>>Есть, по крайней мере, одна хорошая C++ библиотека,
D>Ну так назовите её, поглядим.
OTL
E>>которая использует uncaught_exception в деструкторах для того, чтобы принять решение о том, можно ли порождать исключение или нет, если очистка ресурсов идет с ошибками. Тоже, ведь, на флагах работа построена.
D>Не вижу в этом ничего хорошего. Типичный "Костылиус Вульгарис".
Думаю, все еще проще -- вы не понимаете, почему в C++ вызывается terminate(), поэтому C++ отстой, а вы весь такой в белом.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.