Re[18]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 16:27
Оценка:
Здравствуйте, IB, Вы писали:

C>>Неверно. Повторный выброс исключения в C#/Java затирает предидущее исключение.

IB>Не всегда. Справедливости ради, надо заметить, что есть и InnerException и просто throw без параметров, что в том или ином виде делает доступным оригинальное исключение выше по стеку.
Ну так и в С++ можно извратиться. Например, вручную сделать exception chaining.
Sapienti sat!
Re[21]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 21:03
Оценка:
Здравствуйте, 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]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 21:19
Оценка:
Здравствуйте, eao197, Вы писали:

D>>Просто прелестно. 2008 год на дворе, а у нас глобальные флаги и GetError() во всей своей красе... А люди-то парились, исключения городили... А ну нафиг всё, ведь есть флаги!!!


E>Есть, по крайней мере, одна хорошая C++ библиотека,


Ну так назовите её, поглядим.

E>которая использует uncaught_exception в деструкторах для того, чтобы принять решение о том, можно ли порождать исключение или нет, если очистка ресурсов идет с ошибками. Тоже, ведь, на флагах работа построена.


Не вижу в этом ничего хорошего. Типичный "Костылиус Вульгарис".
Re[22]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 21:31
Оценка:
Здравствуйте, 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]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: IB Австрия http://rsdn.ru
Дата: 07.08.08 21:41
Оценка:
Здравствуйте, nikov, Вы писали:

N>Покажи код, если можно.

Код чего? =) Вызова throw или помещения оригинального исключения внутри catch в InnerException?
Я думаю ты лучше меня знаешь, как это работет.
Мы уже победили, просто это еще не так заметно...
Re[19]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: IB Австрия http://rsdn.ru
Дата: 07.08.08 21:47
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Ну так и в С++ можно извратиться. Например, вручную сделать exception chaining.

Да байта ради. =) Просто ты утверждал, что "Повторный выброс исключения в C#/Java затирает предидущее исключение", что не совсем верно. Более того, в отличии от C++ это делается не "в ручную", а совершенно стандартным способом, через нарошно предназначенное для этого технологическое отверстие.
Мы уже победили, просто это еще не так заметно...
Re[20]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 21:55
Оценка:
Здравствуйте, IB, Вы писали:

C>>Ну так и в С++ можно извратиться. Например, вручную сделать exception chaining.

IB>Да байта ради. =) Просто ты утверждал, что "Повторный выброс исключения в C#/Java затирает предидущее исключение", что не совсем верно.
Нет, это верно. Но с примечанием — можно делать вложенные исключения.
Sapienti sat!
Re[21]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: IB Австрия http://rsdn.ru
Дата: 07.08.08 22:21
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Нет, это верно.

throw без параметров за повторный выброс не считается?

C>Но с примечанием — можно делать вложенные исключения.

Довольно существенное замечание, не находишь?
Мы уже победили, просто это еще не так заметно...
Re[22]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 22:25
Оценка:
Здравствуйте, IB, Вы писали:

C>>Нет, это верно.

IB>throw без параметров за повторный выброс не считается?
Ну выбросит оно предидущее исключение, и что? В С++ так же можно.

C>>Но с примечанием — можно делать вложенные исключения.

IB>Довольно существенное замечание, не находишь?
Не совсем согласен, что оно существенное.
Sapienti sat!
Re[23]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 22:41
Оценка: 3 (1)
Здравствуйте, 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]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 23:08
Оценка: 14 (2) +1
Здравствуйте, 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]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 08.08.08 00:17
Оценка: -6
Здравствуйте, 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. Никакой раскрутки здесь нет.
Re[24]: Exception в Finally
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.08.08 01:53
Оценка:
Здравствуйте, SE, Вы писали:
SE>Может быть уважаемый Sinclair вместо раздачи минусов направо и налево объяснит, с чем он в примере не согласен, и каким образом можно восстановить цепочку исключений случившихся в using после исключения в методе Dispose?
Я привел пример. http://rsdn.ru/forum/message/3050988.1.aspx
Автор: Sinclair
Дата: 07.08.08

SE>Я с благодарностью выслушаю, как это можно сделать. А пример кода был бы просто бальзамом на душу.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Gluk_Kazan  
Дата: 08.08.08 04:53
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

S>Очень простой в этом смысл: сообщаем вызывающему, что детерминистическая финализация не удалась.

S>К примеру, при закрытии файла не удается сделать flush по причине отсутствия доступа к устройству.
S>В отличие от C++, имеем детерминированный способ обработать эту ситуацию. К примеру, попробовать открыть файл на другом устройстве и повторить операцию записи, которая была прервана исключением.

Гмм. Я правильно понял:

1. Flush из деструктора не прошел по причине отсутсвия файла
2. Бросили исключение из деструктора
3. Поймали исключение (где-то)
4. Открыли другой файл и сделали в него Flush
5. Все счастливы ?
Re[26]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 08.08.08 05:01
Оценка: 11 (1) +2
Здравствуйте, drol, Вы писали:

D>Наглая ложь. В Java/C# ничего не теряется. Любое исключение пробрасываемое через функцию может быть поймано и обработано.


Давайте только не вилять и не давать словам собеседника свой смысл, а потом опровергать. А то это уже не диалог.
Это аналогично спору "исключения или возвращаемые значения?"
— Исключение нельзя не обработать
— Чушь, не напишем try-catch и всё

— Возвращаемые значение могут быть не проверены
— Наглая ложь. Возвращаемые значения не теряются. Любое возвращаемое значение можно проверить и обработать.

Исключения отличаются тем, что их придётся обработать. И вы это прекрасно понимаете. Только для спора, конечно, можно и подменить понятия, да? Тут же вам говорят, что возможна ситуация, когда исключение остается необработанным само по себе, без специальных замашек со стороны программиста в виде catch {} (catch ( ... ) {})
Re[17]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Sinclair Россия https://github.com/evilguest/
Дата: 08.08.08 05:04
Оценка:
Здравствуйте, 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
Автор: Sinclair
Дата: 07.08.08
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[27]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 08.08.08 05:31
Оценка:
Здравствуйте, VoidEx, Вы писали:

Кстати, за это надо руки отрывать, или нет?
Просто основной упор делается на то, что, мол, в деструкторах кинуть исключение нельзя.
Ну дак:

template <class exception_type>
void throw_exception(exception_type const & e)
{
  if (!std::uncaught_exception())
    throw e;
  // else...
}


Тогда какие отличия? Только в том, что в шарпе долетает последнее исключение из всей цепочки, а в Си++ — первое. Но во-первых в ветке else можно куда-то что-то записать, а во-вторых, из двух исключений, одно из которых вызвало вереницу обвалов, а второе полетело в самом конце из-за того, что файл не закрылся, лично я выбрал бы первое. Но это отдельная тема для дискуссий. В идеале хорошо было бы получить все исключения.

И не пойму, что мешало в шарпе сделать так, чтобы при броске нового исключения предыдущее не затиралось, а записывалось новому в Inner автоматически?
Re[28]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 08.08.08 05:46
Оценка:
Здравствуйте, VoidEx, Вы писали:

В порыве бреда написал такое:
(Понятно, что вот за такое уже руки надо бы оборвать, но чисто эксперимента ради)

class my_exception : public std::runtime_error
{
public:
    my_exception(std::string const & what) : std::runtime_error(what), inner(0) {}
    virtual ~my_exception() throw()
    {
        delete inner;
    }
    my_exception * inner;
};

my_exception * throwed_exception = 0;

template <class exception_type>
void throw_exception(exception_type const & e)
{
    if (std::uncaught_exception())
    {
        my_exception * last = throwed_exception;
        if (last)
        {
            while (last->inner)
                last = last->inner;
            last->inner = new exception_type(e);
        }
        // else?
    }
    else
    {
        delete throwed_exception;
        throwed_exception = new exception_type(e);
        throw throwed_exception;
    }
}
Re[25]: Exception в Finally
От: SE Украина  
Дата: 08.08.08 07:15
Оценка: 3 (1)
Здравствуйте, Sinclair, Вы писали:

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

SE>>Может быть уважаемый Sinclair вместо раздачи минусов направо и налево объяснит, с чем он в примере не согласен, и каким образом можно восстановить цепочку исключений случившихся в using после исключения в методе Dispose?
S>Я привел пример. http://rsdn.ru/forum/message/3050988.1.aspx
Автор: Sinclair
Дата: 07.08.08


Ну, это отличный пример. Тут вот какая проблема. Помимо тех исключений которые Вы кидаете и ловите в блоках try/catch существуют еще "неудобные" исключения, связанные с нехваткой памяти, шатдауном системы и даже нарушениями выполения кода внутри CLR. И это не фантастика, такие эксепшены ловил каждый кто пробовал писать/генерировать непосредственно IL код.

Их нельзя "проглатывать", их надо пробрасывать наверх.
Как Вы конечно знаете (но остальной аудитории может быть интересно) using — это фактически try/catch c вызовом Dispose в finally.
И вот Вы пробрасываете наверх эти пакостные исключения, чтоб словить их на самом верху и просто закрыть программу с наименьшими потерями для пользователя, а тем временем Dispose из-за указаных причин тоже кидает эксепшен, и как показазано в моем примере, исходный эксепшен, скажем о нарушении работы стека CLR гасится, а остается безобидный об ошибке освобождения ресурса.
Re[22]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 08.08.08 07:31
Оценка: :)
Здравствуйте, drol, Вы писали:

E>>Есть, по крайней мере, одна хорошая C++ библиотека,


D>Ну так назовите её, поглядим.


OTL

E>>которая использует uncaught_exception в деструкторах для того, чтобы принять решение о том, можно ли порождать исключение или нет, если очистка ресурсов идет с ошибками. Тоже, ведь, на флагах работа построена.


D>Не вижу в этом ничего хорошего. Типичный "Костылиус Вульгарис".


Думаю, все еще проще -- вы не понимаете, почему в C++ вызывается terminate(), поэтому C++ отстой, а вы весь такой в белом.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.