Зачем нужен сборщик мусора? Как жить без деструкторов?
От: Аноним  
Дата: 03.08.08 10:52
Оценка: :))) :)))
Изучаю java и возникают вопросы:

Зачем нужен сборщик мусора?
Ведь, деструкторы соберут весь мусор.
Я не помню когда последний раз руками очищал память в с++.


Как можно обходиться без деструкторов?
неужели код
    mutex.lock();//что если обьектов много и какой-то из них забыли закрыть
    try {
        ....
    }
    finally{
        mutex.unlock();
    }


считается удобнее и надежнне чем:
    {
        boost::mutex::lock l(mutex);
        .............
    }


а как быть с очисткой ресурсов (закрытием файлов, различных соединений), тоже руками?
В с++ надо один раз очистить ресурс в деструкторе, а java 30 раз в коде, где этот обьект используется.
Не совсем понятно в чем прелесть такого подхода?


05.08.08 16:06: Перенесено модератором из 'C/C++' — Кодт
Re: Зачем нужен сборщик мусора? Как жить без деструкторов?
От: drol  
Дата: 03.08.08 12:10
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Зачем нужен сборщик мусора?

А>Ведь, деструкторы соберут весь мусор.
А>Я не помню когда последний раз руками очищал память в с++.

Вы, почему-то, рассматриваете только самый примитивный случай: короткоживущие неизменяемые независимые объекты на стеке. А вот давайте возьмём долгоживущую изменяемую древовидную структуру в heap'е. Например, дерево объектов UI. Насколько простым будет управление памятью для такой штуки в C++ ? Вот в managed средах/языках вообще ничего делать не надо; порождать свои собственные структуры такого вида также элементарно.

А>Как можно обходиться без деструкторов?

А>неужели код
А>считается удобнее и надежнне чем:
А>а как быть с очисткой ресурсов (закрытием файлов, различных соединений), тоже руками?

Java имеет неудобный синтаксис в этом месте. В C# же для таких случаев есть специальная конструкция using. Вариант же из C++ лично мне не нравится отсутствием явного обозначения области жизни ресурса.
*Хотя... Если бы это делала IDE, то было бы достаточно.

А>В с++ надо один раз очистить ресурс в деструкторе,


Теоретически. А на практике, при написании деструктора C++ сразу возникает очень много ограничений. Простейший пример: исключение в деструкторе => до свидания развёртка стека и всё остальное.

А>Не совсем понятно в чем прелесть такого подхода?


Надеюсь, что вышеизложенное немного прояснило ситуацию
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 03.08.08 12:48
Оценка:
Здравствуйте, drol, Вы писали:

D>Вы, почему-то, рассматриваете только самый примитивный случай: короткоживущие неизменяемые независимые объекты на стеке. А вот давайте возьмём долгоживущую изменяемую древовидную структуру в heap'е. Например, дерево объектов UI. Насколько простым будет управление памятью для такой штуки в C++ ? Вот в managed средах/языках вообще ничего делать не надо; порождать свои собственные структуры такого вида также элементарно.


В таких случаях я пользуюсь смарт поинтерами.
Существует проблема циклических ссылок, но я ни разу не сталкивался с такой структурой.

D>Java имеет неудобный синтаксис в этом месте. В C# же для таких случаев есть специальная конструкция using. Вариант же из C++ лично мне не нравится отсутствием явного обозначения области жизни ресурса.

D>*Хотя... Если бы это делала IDE, то было бы достаточно.

А>>В с++ надо один раз очистить ресурс в деструкторе,


D>Теоретически. А на практике, при написании деструктора C++ сразу возникает очень много ограничений. Простейший пример: исключение в деструкторе => до свидания развёртка стека и всё остальное.


Не могу представить пример где бы логика требовала исключение в деструкторе. Разумно в деструкторе выполнять действия уничтожающие объекты и соответственно не требующие дополнительных ресурсов. Я считаю, что это совсем не проблема.
Re: Зачем нужен сборщик мусора? Как жить без деструкторов?
От: Roman Odaisky Украина  
Дата: 03.08.08 13:20
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Зачем нужен сборщик мусора?


Для решения, в числе прочих, проблемы циклических ссылок. «Умные указатели» могут решить все проблемы, которые решает сборка мусора, кроме проблемы циклических ссылок.

А еще, сборка мусора порождает меньше синтаксического оверхеда.

Это были преимущества. Недостатки, полагаю, очевидны.
До последнего не верил в пирамиду Лебедева.
Re[3]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 03.08.08 14:59
Оценка: 3 (2)
Здравствуйте, Аноним, Вы писали:

D>>Вы, почему-то, рассматриваете только самый примитивный случай: короткоживущие неизменяемые независимые объекты на стеке. А вот давайте возьмём долгоживущую изменяемую древовидную структуру в heap'е. Например, дерево объектов UI. Насколько простым будет управление памятью для такой штуки в C++ ? Вот в managed средах/языках вообще ничего делать не надо; порождать свои собственные структуры такого вида также элементарно.

А>В таких случаях я пользуюсь смарт поинтерами.

Ну вот видите. Вам приходится добавлять целый синтаксический + семантический уровень с соответствующим полным комплектом развлечений. В managed же средах/языках Вы освобождены от этих чисто технических аспектов.

А>Существует проблема циклических ссылок, но я ни разу не сталкивался с такой структурой.


Ещё бы. Я тоже старался с ними не сталкиваться во времена работы на C++ А вот на Java/.NET что хочу, то и ворочу

D>>Теоретически. А на практике, при написании деструктора C++ сразу возникает очень много ограничений. Простейший пример: исключение в деструкторе => до свидания развёртка стека и всё остальное.

А>Не могу представить пример где бы логика требовала исключение в деструкторе.

А как вызывающему коду нормально узнать, что при очистке случилась ерунда ?

А>Разумно в деструкторе выполнять действия уничтожающие объекты и соответственно не требующие дополнительных ресурсов.


А это противоречит Вашему тезису о деструкторах как освободителях ресурсов. Вот достаточно простой пример ресурса, при очистке требующего как массы действий, так и новых ресурсов: распределённая транзакция.
Re[4]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: shrecher  
Дата: 03.08.08 15:18
Оценка:
Здравствуйте, drol, Вы писали:

D>Ну вот видите. Вам приходится добавлять целый синтаксический + семантический уровень с соответствующим полным комплектом развлечений. В managed же средах/языках Вы освобождены от этих чисто технических аспектов.


Ну почти освобождены только до моментов пока вы считаете, что память бесканечна или не уперлись в вызов unmanaged кода.
Re: Зачем нужен сборщик мусора? Как жить без деструкторов?
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.08.08 15:35
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Зачем нужен сборщик мусора?

А>Ведь, деструкторы соберут весь мусор.
А>Я не помню когда последний раз руками очищал память в с++.

Например, чтобы не морочить свою голову такими понятиями, как время жизни объекта. В идеале, объект жив, пока вы можете до него добраться. Как только вы потеряли возможность до него добраться, вам больше не интересно, что происходит с ним самим и его ресурсами.

К сожалению, это плохо согласуется с традиционным для C++ подходом, когда создание/уничтожение объекта имеет побочные эффекты (не важно, в виде захвата мутекса, создания базы данных на диске и т.п. Важно, что эти побочнные эффекты видны в программе не через "значение" объекта).
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 03.08.08 15:41
Оценка:
это плохо согласуется не только с С++, но так же с трандиционным подходом в файловых системах, СУБД, указанных автором поста примитивов синхронизации и вообще любых ресурсов с ограниченным количеством пользователей, которые надо ОБЯЗАТЕЛЬНО детерминистически освобождать. Контроль за освобождением памяти это самое простое.
Re[3]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.08.08 17:08
Оценка:
Здравствуйте, Аноним, Вы писали:

А>это плохо согласуется не только с С++, но так же с трандиционным подходом в файловых системах, СУБД, указанных автором поста примитивов синхронизации и вообще любых ресурсов с ограниченным количеством пользователей, которые надо ОБЯЗАТЕЛЬНО детерминистически освобождать. Контроль за освобождением памяти это самое простое.


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

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

Прятать же захват глобального ресурса в конструктор локального объекта, а освобождение в деструктор — далеко не самая светлая идея.
Re[5]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 03.08.08 17:09
Оценка:
Здравствуйте, shrecher, Вы писали:

D>>Ну вот видите. Вам приходится добавлять целый синтаксический + семантический уровень с соответствующим полным комплектом развлечений. В managed же средах/языках Вы освобождены от этих чисто технических аспектов.


S>Ну почти освобождены только до моментов пока вы считаете, что память бесканечна


Ничего не понял. Причём здесь "бесконечная память" какая-то ???

S> или не уперлись в вызов unmanaged кода.


Совершенно верно, unmanaged-код — наш главный враг
А с managed-кодом всё в полном порядке.

*Singularity/Midori forever!!!
Re[4]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 03.08.08 17:14
Оценка: -1
А>>это плохо согласуется не только с С++, но так же с трандиционным подходом в файловых системах, СУБД, указанных автором поста примитивов синхронизации и вообще любых ресурсов с ограниченным количеством пользователей, которые надо ОБЯЗАТЕЛЬНО детерминистически освобождать. Контроль за освобождением памяти это самое простое.

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


Pzz>Таких конструктов лучше избегать, они — источники сложных ошибок, причем ошибок не только в коде, но и в архитектуре. Если избежать невозможно, то надо предусмотреть какое-то централизованное управление каждым глобальным рисурсом, с явным и ясным интерфейсом.

Слишком много слов выше...

Pzz>Прятать же захват глобального ресурса в конструктор локального объекта, а освобождение в деструктор — далеко не самая светлая идея.

Очень удобно я вам скажу. Как раз такие объекты обычно захватываются на недолгое время и концепция автоматических объектов очень удобна оказывается. Но если вы ее не использовали хотябы полгода вам не понять.
Re[5]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.08.08 17:22
Оценка:
Здравствуйте, Аноним, Вы писали:

Pzz>>Прятать же захват глобального ресурса в конструктор локального объекта, а освобождение в деструктор — далеко не самая светлая идея.

А>Очень удобно я вам скажу. Как раз такие объекты обычно захватываются на недолгое время и концепция автоматических объектов очень удобна оказывается. Но если вы ее не использовали хотябы полгода вам не понять.

Очень удобно, знаете ли, решать все вопросы с помощью маузера. Только работает не долго — пока в ногу себе первый раз не выстрелишь.
Re[6]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 03.08.08 17:24
Оценка:
Pzz>>>Прятать же захват глобального ресурса в конструктор локального объекта, а освобождение в деструктор — далеко не самая светлая идея.
А>>Очень удобно я вам скажу. Как раз такие объекты обычно захватываются на недолгое время и концепция автоматических объектов очень удобна оказывается. Но если вы ее не использовали хотябы полгода вам не понять.

Pzz>Очень удобно, знаете ли, решать все вопросы с помощью маузера. Только работает не долго — пока в ногу себе первый раз не выстрелишь.

Тоже самое можно сказать про любой другой предмет обихода
Re[6]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: shrecher  
Дата: 03.08.08 17:26
Оценка: -1 :)
Здравствуйте, drol, Вы писали:

S>>Ну почти освобождены только до моментов пока вы считаете, что память бесканечна


D>Ничего не понял. Причём здесь "бесконечная память" какая-то ???


GC не оптимально расходует память. К примеру, если создал 10 м объектов, но используешь только 100, а остальные уже не надо бы держать в мозгах и их уже можно разрушить, но вся эта куча объектов не может быть удалена автоматически, если неизвесна семантика твоей программы.

Поэтому и получается, что программы на Java столько памяти и кушают.
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.08.08 17:28
Оценка:
Здравствуйте, Аноним, Вы писали:

Pzz>>Очень удобно, знаете ли, решать все вопросы с помощью маузера. Только работает не долго — пока в ногу себе первый раз не выстрелишь.

А>Тоже самое можно сказать про любой другой предмет обихода

Ну вы ведь не хотите содержательно вопрос обсуждать — для вас слишком много букв получается
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 03.08.08 17:39
Оценка:
Здравствуйте, shrecher, Вы писали:

S>>>Ну почти освобождены только до моментов пока вы считаете, что память бесканечна

D>>Ничего не понял. Причём здесь "бесконечная память" какая-то ???
S>GC не оптимально расходует память. К примеру, если создал 10 м объектов, но используешь только 100, а остальные уже не надо бы держать в мозгах и их уже можно разрушить,

Продолжаю непонимать. Зачем Вы создали и держите полноценные ссылки на 10М объектов, если используете только 100 ???
Re[8]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: shrecher  
Дата: 03.08.08 17:46
Оценка:
Здравствуйте, drol, Вы писали:

S>>GC не оптимально расходует память. К примеру, если создал 10 м объектов, но используешь только 100, а остальные уже не надо бы держать в мозгах и их уже можно разрушить,


D>Продолжаю непонимать. Зачем Вы создали и держите полноценные ссылки на 10М объектов, если используете только 100 ???


Мы же говорим о "ленивом" программисте, который пишет не раздумывая над тонкостями аллокации и деаллокации объектов, а именно GC отучает программиста думать о памяти: надо создать объект — создай, а удаление где-то за кадром. А если программист начнет думать о ссылках на объекты и поведении GC, то и вызвать деструктор или создать умный указатель для него больщой проблемы не будет. Вот мы и вернулись к вопросу топика "Зачем нужен сборщик мусора?".
Re[9]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 03.08.08 18:53
Оценка: +1
Здравствуйте, shrecher, Вы писали:

D>>Продолжаю непонимать. Зачем Вы создали и держите полноценные ссылки на 10М объектов, если используете только 100 ???

S>Мы же говорим о "ленивом" программисте,

Нет, мы говорим о механизмах распределения памяти.

S>который пишет не раздумывая над тонкостями аллокации и деаллокации объектов,


Неквалифицированный программист пишет ерунду всегда. Хотя соглашусь: в managed-средах вероятность более-менее адекватной работы им написанного всё-таки повыше...

S>а именно GC отучает программиста думать о памяти:


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

S>надо создать объект — создай, а удаление где-то за кадром.


Именно так. Надо — создай. А вот "надо 100 — создай 10М" это совершенно из другой оперы.

S>А если программист начнет думать о ссылках на объекты и поведении GC,


Квалифицированный программист думает об этом, бо знает какие ошибки распределения памяти бывают в managed-средах.

S>то и вызвать деструктор или создать умный указатель для него больщой проблемы не будет.


Для квалифицированного — не будет. Для него также не будет проблемой всё это и на ассемблере написать. Вопрос только во времени: вместо ковыряния с регистрами/деструкторами лучше позаниматься чем-нибудь полезным...
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.08.08 20:35
Оценка:
Здравствуйте, shrecher, Вы писали:

S>GC не оптимально расходует память. К примеру, если создал 10 м объектов, но используешь только 100, а остальные уже не надо бы держать в мозгах и их уже можно разрушить, но вся эта куча объектов не может быть удалена автоматически, если неизвесна семантика твоей программы.


S>Поэтому и получается, что программы на Java столько памяти и кушают.


Я не производил аккуратных замеров, но по ощущениям программы на яве кушают заметно больше памяти, чем программы, скажем, на питоне. И тот и другой языки используют GC. И вообще, когда GC был придуман (в LISP'е, в конце 50-х) , столько памяти даже представить себе было нельзя. Так что в пожирании памяти все же не GC сам ои себе виноват, а чьи-то кривые рученки
Re[8]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: shrecher  
Дата: 04.08.08 04:55
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Так что в пожирании памяти все же не GC сам ои себе виноват, а чьи-то кривые рученки


Я, собственно, ничего не имею против GC. Но с другой стороны, как и любое средство GC вносит сущетвенный overhead в работу программы. В тоже время, использование легковесных уных указателей и деструторов легко заменяют GC для очень большого круга задач.
Re[10]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: codelord  
Дата: 04.08.08 08:00
Оценка: -3 :))
Вот можно сколько угодно говорить насколько здорово в Яве сделано управление памятью.
И применять этот код практически всегда java + СУБД
Только вот когда дело касается эффективности, то все эти штучки дрючки на ( ...-машинах )
нервно курят. И разные это вещи каждому свое которые не корректно сравнивать ( С++ компилируемый язык, точка ). Мне нравится когда код работает с максимальной эффективностью очень быстро.
и это не для интерпретаторов на ( ...-машинах )

Сообщение отредактировано модератором. ДХ
Re: Зачем нужен сборщик мусора? Как жить без деструкторов?
От: MasterZiv СССР  
Дата: 04.08.08 09:08
Оценка:
Аноним 50 пишет:

> Изучаю java и возникают вопросы:

>
> *Зачем нужен сборщик мусора?*
> *Как можно обходиться без деструкторов?*

У вас в голове — каша. Как связаны деструкторы с освобожнением
памяти ? Ответ — никак. Деструктор ДЕИНИЦИАЛИЗИРУЕТ объект,
а не освобождает память. Это можно делать как перед освобождением
памяти, так и без неё. Также никто не запрещает в языке с garbage
collector иметь и вызывать деструкторы, там просто в другом проблема —
в том, чтобы снизить накладные расходы по раскрутке стека.

Так что вы сначала разберитесь с этим.

Конечно вы правы, Java — это заметная деградация по сравнению
с С++, но в этом есть и плюсы — быстрая раскрутка стека и дешёвые
исключения. А так — всё делать руками, конечно, в finally.
Posted via RSDN NNTP Server 2.1 beta
Re: Зачем нужен сборщик мусора? Как жить без деструкторов?
От: Vamp Россия  
Дата: 04.08.08 13:28
Оценка:
...
Закон парных случаев в действии. Только в пятницу об этом думал именно в таких выражениях.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 04.08.08 13:52
Оценка:
а зачем деинициализированному объекту память держать? исходим из того что после деинициализации вызов любого метода объекта приведет к ошибке
Re[3]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 04.08.08 14:20
Оценка:
Здравствуйте, Аноним, Вы писали:

А>а зачем деинициализированному объекту память держать? исходим из того что после деинициализации вызов любого метода объекта приведет к ошибке


Что бы новый объект на его месте инициализировать =)
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 04.08.08 14:33
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Аноним 50 пишет:


>> Изучаю java и возникают вопросы:

>>
>> *Зачем нужен сборщик мусора?*
>> *Как можно обходиться без деструкторов?*

MZ>У вас в голове — каша. Как связаны деструкторы с освобожнением

MZ>памяти ? Ответ — никак.
............
MZ>Так что вы сначала разберитесь с этим.

Я задал два разных вопроса, тех которые меня больше всего интересовали. Просто вы понимаете вопросы так, как вам хочется.


MZ>Конечно вы правы, Java — это заметная деградация по сравнению

MZ>с С++, но в этом есть и плюсы — быстрая раскрутка стека и дешёвые
MZ>исключения. А так — всё делать руками, конечно, в finally.
Re[4]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 04.08.08 14:38
Оценка:
А>>а зачем деинициализированному объекту память держать? исходим из того что после деинициализации вызов любого метода объекта приведет к ошибке
А>Что бы новый объект на его месте инициализировать =)
А причем тут GC? Обычный heap manager тоже самое делает
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 04.08.08 14:40
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>У вас в голове — каша. Как связаны деструкторы с освобожнением

MZ>памяти ? Ответ — никак.

В C++ вполне себе связаны. Раскрутка стека, или там зачистка объектов-членов в случае delete, вызывают исполнение деструкторов прямо во внутреннем контексте runtime'а. Что в свою очередь налагает ограничения на содержимое деструкторов, и в итоге исходная проблема не решена.
Re[4]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 04.08.08 14:45
Оценка:
Здравствуйте, drol, Вы писали:

D>Ну вот видите. Вам приходится добавлять целый синтаксический + семантический уровень с соответствующим полным комплектом развлечений. В managed же средах/языках Вы освобождены от этих чисто технических аспектов.


Этот уровень создан до меня и является стандартом для любого программиста и не требует никаких усилий.

зы
Много шуму на тему того, что C++ — язык прошлого и т.д. А вот Java — весь такой удобный, и одно удовольствие писать на нем, и освобождает программиста от рутины...
Хотя я думаю иначе(пока что, дальше видно будет).
Re[11]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 04.08.08 14:52
Оценка: 1 (1) -1
Здравствуйте, codelord, Вы писали:

C>Только вот когда дело касается эффективности,


Какой из них ?

C>И разные это вещи каждому свое которые не корректно сравнивать ( С++ компилируемый язык, точка ).

C>...
C>и это не для интерпретаторов на ( ...-машинах )

И Java, и C# — тоже компилируемые языки. Так что действительно точка.
*В смысле вопроса о Вашей полной некомпетентности в области subj'а.

C>Мне нравится когда код работает с максимальной эффективностью очень быстро.


Я так понял, что Вы пишете исключительно в машинных кодах ?
Re[3]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: MasterZiv СССР  
Дата: 04.08.08 15:02
Оценка:
Аноним 373 пишет:

> а зачем деинициализированному объекту память держать? исходим из того

> что после деинициализации вызов любого метода объекта приведет к ошибке
Да господи, да мало ли зачем !
Ну например — чтобы другой аналогичный (или вообще другой) объект в этой
памяти создать.
Posted via RSDN NNTP Server 2.1 beta
Re: Зачем нужен сборщик мусора? Как жить без деструкторов?
От: MasterZiv СССР  
Дата: 04.08.08 15:09
Оценка:
Аноним 50 пишет:
> Изучаю java и возникают вопросы:

Отвечаем ЧЁТКО на ЧЁТКО ПОСТАВЛЕННЫЕ ВОПРОСЫ. Без демагогий.

> *Зачем нужен сборщик мусора?*


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

> Ведь, деструкторы соберут весь мусор.


Деструкторы память не освобождают.

> *Как можно обходиться без деструкторов?*


Использовать finally или другие (в других языках, не в Java)
защитные огороды стека. Это только для С++ программистов кажется
неестественно, потому что они к этому привыкли. Теоретически
написание finally и написание кода в деструкторе — проблемы одного
порядка сложности. Да, в Java это немного хуже, потому что
код в деструкторе надо не забыть написать один раз, а код в
finally — КАЖДЫЙ раз. Но если *тебе так нравится Java*, то тебе
просто ничего не остается делать. Если тебе Java не нравится —
изучай более другие языки программирования (не имею в виду C++
в данном случае, видимо, его ты уже знаешь).
Posted via RSDN NNTP Server 2.1 beta
Re[12]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: codelord  
Дата: 04.08.08 15:10
Оценка: -8 :)))
Соберите объектник слинкуйте и запустите хоть где нибудь без Java интерпретатора в кучу мегов
Так что не надо передергивать и всякие там байт коды называть бинарниками ок?

RTFM в общем. учите матчасть!!
точка.

C>>Мне нравится когда код работает с максимальной эффективностью очень быстро.


D>Я так понял, что Вы пишете исключительно в машинных кодах ?


Сообщение отредактировано модератором. ДХ
Re[3]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: MasterZiv СССР  
Дата: 04.08.08 15:12
Оценка:
drol пишет:

> В C++ вполне себе связаны. Раскрутка стека, или там зачистка

> объектов-членов в случае delete, вызывают исполнение деструкторов прямо
> во внутреннем контексте runtime'а. Что в свою очередь налагает
> ограничения на содержимое деструкторов, и в итоге исходная проблема не
> решена.

Если одно является следствием другого, являются ли эти вещи связанными ?
Знаешь, вопрос филосовский. тем более что деструктор может быть вызван
и НЕ в результате освобождения памяти в процессе delete, раскрутки стека
и деинициализации глобальных и статических объектов программы.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Vamp Россия  
Дата: 04.08.08 15:14
Оценка:
MZ>Деструкторы память не освобождают.
Это смотря что написать в деструкторе. Например, деструктор смартпойнтера именно что освобождает память.

MZ>Да, в Java это немного хуже, потому что

MZ>код в деструкторе надо не забыть написать один раз, а код в
MZ>finally — КАЖДЫЙ раз.
Ага. И это кошмар.
Да здравствует мыло душистое и веревка пушистая.
Re[4]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 04.08.08 15:16
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Что бы новый объект на его месте инициализировать =)


Эка у меня номер сегодня злой получился =)))
Re[3]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: MasterZiv СССР  
Дата: 04.08.08 15:19
Оценка:
Vamp пишет:
> MZ>Деструкторы память не освобождают.
> Это смотря что написать в деструкторе. Например, деструктор
> смартпойнтера именно что освобождает память.

Деструктор данного объекта не освобождает память, занимаемую
данным объектом. Он только осуществляет деинициализацию
этого объекта.

> Ага. И это кошмар.

> Да здравствует мыло душистое и веревка пушистая.

Ну им-то нравится !
Вообще, прикольно, что тема эта всплывает именно здесь, в С++.
Жавские пингвины-то даже про это не задумаются обычно.
Posted via RSDN NNTP Server 2.1 beta
от модератора
От: WolfHound  
Дата: 04.08.08 15:21
Оценка:
Здравствуйте, codelord, Вы писали:

C>Да ну нах, что за чушь.

1)Не матерись.
2)Сбавь обороты.
3)Не оверквоть.
4)Перестань заниматься топпостингом.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: jazzer Россия Skype: enerjazzer
Дата: 04.08.08 15:43
Оценка: 5 (4) +3
Здравствуйте, MasterZiv, Вы писали:

MZ>Использовать finally или другие (в других языках, не в Java)

MZ>защитные огороды стека. Это только для С++ программистов кажется
MZ>неестественно, потому что они к этому привыкли. Теоретически
MZ>написание finally и написание кода в деструкторе — проблемы одного
MZ>порядка сложности.

Не вполне. См. ниже.

MZ>Да, в Java это немного хуже, потому что

MZ>код в деструкторе надо не забыть написать один раз, а код в
MZ>finally — КАЖДЫЙ раз.

И не только это.
* Деструктор инкапсулирует очистку, что само по себе хорошо: не возникает никаких левых внешних и взаимных зависимостей и прочие плюсы инкапсуляции.
* Деструкторы вызываются только для уже сконструированных объектов (т.е. если к моменту выброса исключения какой-то обеъкт еще не создался, то его деструктор не вызовется). В ситуации с finally у тебя один блок на все объекты, а это означает, что придется городить какой-то огород вокруг твоих объектов, чтобы внутри finally понять, у кого звать деструктор, а у кого — нет.
* Порядок вызова деструкторов устанавливается автоматически. В принципе невозможно "забыть" вызвать деструктор или позвать их не в том порядке. В случае с finally придется за всем этим следить руками.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 04.08.08 15:47
Оценка:
MZ>Да господи, да мало ли зачем !
MZ>Ну например — чтобы другой аналогичный (или вообще другой) объект в этой
MZ>памяти создать.
Обычный С++ ный менеджер кучи именно этим занимается — при free часто не отдает память системе, а держит ее на "на будущее". GC тут совершенно не концептуален.
Re[4]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 04.08.08 16:31
Оценка:
Здравствуйте, MasterZiv, Вы писали:

>> В C++ вполне себе связаны. Раскрутка стека, или там зачистка

>> объектов-членов в случае delete, вызывают исполнение деструкторов прямо
>> во внутреннем контексте runtime'а.

MZ>Если одно является следствием другого, являются ли эти вещи связанными ?

MZ>Знаешь, вопрос филосовский.

Вопрос очевидный. Деструктор тем и отличается от всех остальных функций-членов, что непосредственно вызывается в указанных выше случаях.

MZ>тем более что деструктор может быть вызван

MZ>и НЕ в результате

Может, одно другому никак не мешает.
Re[3]: Вывод
От: Аноним  
Дата: 04.08.08 16:31
Оценка:
Здравствуйте, jazzer, Вы писали:

J>И не только это.

J> * Деструктор инкапсулирует очистку, что само по себе хорошо: не возникает никаких левых внешних и взаимных зависимостей и прочие плюсы инкапсуляции.
J> * Деструкторы вызываются только для уже сконструированных объектов (т.е. если к моменту выброса исключения какой-то обеъкт еще не создался, то его деструктор не вызовется). В ситуации с finally у тебя один блок на все объекты, а это означает, что придется городить какой-то огород вокруг твоих объектов, чтобы внутри finally понять, у кого звать деструктор, а у кого — нет.
J> * Порядок вызова деструкторов устанавливается автоматически. В принципе невозможно "забыть" вызвать деструктор или позвать их не в том порядке. В случае с finally придется за всем этим следить руками.

Вот это САМОЕ ГЛАВНОЕ что я хотел услышать.
Re: Зачем нужен сборщик мусора? Как жить без деструкторов?
От: Анатолий Широков СССР  
Дата: 04.08.08 17:24
Оценка:
В С++ нет проблемы потерянного исключения, поскольку деструктору объекта запрещено выпускать наружу любые исключения (если это не так, то это UB, если мне не изменяет память), а вот в Java "потерять" исключение проще простого:

try
{
    throw new FirstException();
}
finally
{
      throw new SecondExpection(); // все, пользователь никогда не узнает о FirstException
}
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Vamp Россия  
Дата: 04.08.08 17:29
Оценка:
А вот тут много говорят о исключениях из деструктора. А я вообще-то не вполне понимаю, какой может быть смысл в исключениях, брошенных из деструктора. Объект умер, его уже не оживить. Что должно означать исключение с точки зрения логики программы?
Да здравствует мыло душистое и веревка пушистая.
Re[3]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 04.08.08 17:31
Оценка:
Здравствуйте, jazzer, Вы писали:

J>И не только это.

J> * Деструктор инкапсулирует очистку,

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

J> * Деструкторы вызываются только для уже сконструированных объектов (т.е. если к моменту выброса исключения какой-то обеъкт еще не создался, то его деструктор не вызовется). В ситуации с finally у тебя один блок на все объекты,


Блоков будет столько, сколько Вы захочете. И логически правильный way — заводить по try/finally на каждый взятый ресурс. Если же хочется простоты, переходите на C#. Там IDisposable и using решают сей вопрос, и даже можно выбирать/комбинировать, в зависимости от условий, необходимое поведение: автоматику using, или возможности точного реагирования на исключения через try/catch/finally.

J> * Порядок вызова деструкторов устанавливается автоматически.


В случае нормальных вложенных try/finally/catch/using — аналогично.

J>В принципе невозможно "забыть" вызвать деструктор


Вопрос же "забыть" решается правильным инструментарием в IDE. Кстати, тоже преимущество managed-сред. Синтаксис C++ делает практически невозможным реализацию ПО типа ReSharper'а.
Re[3]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Анатолий Широков СССР  
Дата: 04.08.08 17:43
Оценка:
Здравствуйте, Vamp, Вы писали:

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


Я тоже хотел бы услышать аргументацию drol-а на этот счет.
Re[4]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Анатолий Широков СССР  
Дата: 04.08.08 17:59
Оценка:
Здравствуйте, drol, Вы писали:

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


J>>И не только это.

J>> * Деструктор инкапсулирует очистку,

D>В managed-языках Вам также ничто не мешает инкапсулировать очистку в соответствующем методе. Более того, в отличии от C++, Вы при этом неограничены в использовании языковых конструкций. Например, можете спокойно бросать исключения...


Только я должен постоянно помнить о вызове метода "освобождения ресурсов". И при таком подходе, я запрасто могу скрыть первичное исключение, если вызов метода делаю в finally и этот метод бросает исключение.

J>> * Деструкторы вызываются только для уже сконструированных объектов (т.е. если к моменту выброса исключения какой-то обеъкт еще не создался, то его деструктор не вызовется). В ситуации с finally у тебя один блок на все объекты,


D>Блоков будет столько, сколько Вы захочете. И логически правильный way — заводить по try/finally на каждый взятый ресурс. Если же хочется простоты, переходите на C#. Там IDisposable и using решают сей вопрос, и даже можно выбирать/комбинировать, в зависимости от условий, необходимое поведение: автоматику using, или возможности точного реагирования на исключения через try/catch/finally.


Код кетода превращается в нечитабельный серпантин.

J>> * Порядок вызова деструкторов устанавливается автоматически.


D>В случае нормальных вложенных try/finally/catch/using — аналогично.


Опятьже, нечитаемая портянка.

J>>В принципе невозможно "забыть" вызвать деструктор


D>Вопрос же "забыть" решается правильным инструментарием в IDE. Кстати, тоже преимущество managed-сред. Синтаксис C++ делает практически невозможным реализацию ПО типа ReSharper'а.


C++ дает гораздо больше — гарантию вызова деструктора автоматического объекта. Кивать на IDE не имея гарантии со стороны языка — ну что же, аргумент, если других нет.

Вообщем, резюме такое: все проблемы GC сводяться к одной — к отсутствию понятия жизненного цикла объекта, а именно, недерминированному времени его кончины.
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 04.08.08 18:03
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>В С++ нет проблемы потерянного исключения,


Вы всё перевернули с ног на голову. Это как раз в Java нет такой проблемы, бо как напишете, так и будет работать. Захотите ловить — будет ловить, захотите "терять" — будет "терять", захотите накапливать — будет накапливать и т.д.

А в C++ в этом случае Вас, практически всегда, ожидает только доблестный terminate()

АШ>поскольку деструктору объекта запрещено выпускать наружу любые исключения (если это не так, то это UB, если мне не изменяет память),


Изменяет.
Re[3]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 04.08.08 18:11
Оценка:
Здравствуйте, Vamp, Вы писали:

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


Излагаю n-дцатый раз:

Оппоненты выдвигают тезис о деструкторе C++ как замечательном методе очистки/освобождения/деинициализации ресурса. Однако не могут ответить на элементарный вопрос: как вызывающему коду нормально узнать о том, что очистка/освобождение/деинициализация "не прошла" ?

В качестве ресурса пусть будет, например, распределённая транзакция. Требует нетривиальной очистки, в частности связанной с запросом новых ресурсов.
Re[4]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Vamp Россия  
Дата: 04.08.08 18:16
Оценка: 1 (1) +2
D>Оппоненты выдвигают тезис о деструкторе C++ как замечательном методе очистки/освобождения/деинициализации ресурса. Однако не могут ответить на элементарный вопрос: как вызывающему коду нормально узнать о том, что очистка/освобождение/деинициализация "не прошла" ?

Речь не мальчика, но мужа. Ответ: метод RAII применяется в том случае, где "не прошла" — либо не бывает, либо не предусматривает никакого исправления. Коммит в транзакции — НЕ RAII, потому что не прошедший коммит реально требует действия. Закрытия файлового дескриптора — вполне RAII, там сбоев не бывает.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: shrecher  
Дата: 04.08.08 18:49
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>В С++ нет проблемы потерянного исключения...., а вот в Java "потерять" исключение проще простого:


В С++ запросто можно написать подобный код

try
{
    throw FirstException();
}
catch(...)
{
      throw SecondExpection(); // все, пользователь никогда не узнает о FirstException
}
Re[3]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 04.08.08 18:55
Оценка:
Здравствуйте, shrecher, Вы писали:

S>Здравствуйте, Анатолий Широков, Вы писали:


АШ>>В С++ нет проблемы потерянного исключения...., а вот в Java "потерять" исключение проще простого:


S>В С++ запросто можно написать подобный код


S>
S>try
S>{
S>    throw FirstException();
S>}
S>catch(...)
S>{
S>      throw SecondExpection(); // все, пользователь никогда не узнает о FirstException
S>}
S>



и что?
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: sraider http://dvinogradov.blogspot.com
Дата: 04.08.08 19:05
Оценка:
А>>Зачем нужен сборщик мусора?
RO>Для решения, в числе прочих, проблемы циклических ссылок. «Умные указатели» могут решить все проблемы, которые решает сборка мусора, кроме проблемы циклических ссылок.

даже умный указатель garbage_collected_ptr не решит эту проблему?
Re[5]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 04.08.08 19:41
Оценка: +2
Здравствуйте, Vamp, Вы писали:

D>>Оппоненты выдвигают тезис о деструкторе C++ как замечательном методе очистки/освобождения/деинициализации ресурса. Однако не могут ответить на элементарный вопрос: как вызывающему коду нормально узнать о том, что очистка/освобождение/деинициализация "не прошла" ?


V>Речь не мальчика, но мужа. Ответ: метод RAII применяется в том случае, где "не прошла" — либо не бывает, либо не предусматривает никакого исправления. Коммит в транзакции — НЕ RAII, потому что не прошедший коммит реально требует действия.


Ну так и что Вы пишете на C++ в этом случае ?

V>Закрытия файлового дескриптора — вполне RAII, там сбоев не бывает.


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

Итого:

Подход с деструкторами-очистителями в C++ очень сильно ограничен, и нормально покрывает только самые простые (и по-большей части чисто технические) случаи, типа каких-нибудь smart pointer'ов. Любая очистка требующая новых ресурсов/допускающая отказы, сразу же вызывает тот жуткий код, который Вы напишете в ответ на вопрос из 1-го абзаца

*Кстати, обратите внимание на сам термин RAII == Resource Acquisition Is Initialization. Он ведь очень показателен, бо ни слова про какое-то там освобождение чего-бы то ни было не содержит. А всего лишь постулирует однофазный захват ресурса непосредственно при создании объекта
Re[3]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Анатолий Широков СССР  
Дата: 04.08.08 19:43
Оценка:
Здравствуйте, shrecher, Вы писали:

S>Здравствуйте, Анатолий Широков, Вы писали:


АШ>>В С++ нет проблемы потерянного исключения...., а вот в Java "потерять" исключение проще простого:


S>В С++ запросто можно написать подобный код


S>
S>try
S>{
S>    throw FirstException();
S>}
S>catch(...)
S>{
S>      throw SecondExpection(); // все, пользователь никогда не узнает о FirstException
S>}
S>


Есть разница, все же, между catch(...) и finally. catch(...) — я перехватываю все исключения и делаю это сознательно, finally — я попадаю сюда в независимости от того, было ли исключение или нет. Так вот, попав в finally по причине исключения я, выбросил SecondExpection, ввожу пользователя в заблуждение, поскольку он получит наведенное исключение, а не первопричину.
Re[4]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: MasterZiv СССР  
Дата: 04.08.08 19:44
Оценка:
drol пишет:

> Вопрос же "забыть" решается правильным инструментарием в IDE. Кстати,

> тоже преимущество managed-сред.

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

Синтаксис C++ делает практически
> невозможным реализацию ПО типа ReSharper'а.

Да думать надо, когда пишешь.
Posted via RSDN NNTP Server 2.1 beta
Re[6]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Vamp Россия  
Дата: 04.08.08 20:00
Оценка:
D>Ну так и что Вы пишете на C++ в этом случае ?
Напишу соответствующий код.

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

Ну и какое же там восстановление возможно? Вот стала у вас система раком и fclose возвращает ошибку. Что делать будете?
Да здравствует мыло душистое и веревка пушистая.
Re[5]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 04.08.08 20:05
Оценка: 1 (1)
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Только я должен постоянно помнить о вызове метода "освобождения ресурсов".


Как мы уже установили в параллельной части треда: и в C++ Вы тоже обязаны помнить об освобождении ресурсов, чьё освобождение нельзя запихать в жёсткие ограничения деструктора.

*А вот в Java/C# Вас спасут IDEA/ReSharper

АШ>И при таком подходе, я запрасто могу скрыть первичное исключение, если вызов метода делаю в finally и этот метод бросает исключение.


Вы можете делать что угодно, в этом и преимущество. В C++ же у Вас, по-факту, только terminate()...

D>>Блоков будет столько, сколько Вы захочете. И логически правильный way — заводить по try/finally на каждый взятый ресурс. Если же хочется простоты, переходите на C#. Там IDisposable и using решают сей вопрос, и даже можно выбирать/комбинировать, в зависимости от условий, необходимое поведение: автоматику using, или возможности точного реагирования на исключения через try/catch/finally.


АШ>Код кетода превращается в нечитабельный серпантин.


Код будет таким, каким Вы захотите.

*Если у Вас используется 3+ вложенных ресурсов — это хороший повод задуматься над рефакторингом метода/архитектуры

АШ>C++ дает гораздо больше — гарантию вызова деструктора автоматического объекта.


Деструктора, который даже исключение не может бросить, дабы сообщить о проблемах очистки... Это не "больше", это "кандалы"...

АШ>Кивать на IDE не имея гарантии со стороны языка — ну что же, аргумент, если других нет.


*Не работавшим с IDEA/ReSharper, наверное, действительно понять сложно

Есть много синтаксических/семантических вещей, которые нужны в одних условиях, не требуются в других и избирательно необходимы в третьих. Причём срез этих условий может проходить по любой области: по стеку вызовов, по слоям стандартной библиотеки классов и т.д.
И лучше сделать язык/runtime удобным для различного рода инструментов а-ля ReSharper, чем пытаться сгородить язык/компилятор удовлетворяющий всей этой n-мерной массе противоречивых требований.

IDisposable-объекты, или там checked exceptions, например, как раз такой категории штуки...

АШ>Вообщем, резюме такое: все проблемы GC сводяться к одной — к отсутствию понятия жизненного цикла объекта, а именно, недерминированному времени его кончины.


Гы! Это не проблема, это решение проблемы.

GC управляет памятью, вот его предназначение. А жизненный цикл объектов это забота программиста, бо GC не знает смысла программы выше уровня языка. И вместо того чтобы дёргать какие-то там деструкторы вне нормального контекста исполнения программы (как поступает C++), managed-языки и -среды предоставляют набор вполне удобных механизмов — try/catch/finally/using — для нормального детерминированного управления объектом.
Re[6]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Аноним  
Дата: 04.08.08 20:36
Оценка:
Здравствуйте, drol, Вы писали:

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


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

D>Итого:


D>Подход с деструкторами-очистителями в C++ очень сильно ограничен, и нормально покрывает только самые простые (и по-большей части чисто технические) случаи, типа каких-нибудь smart pointer'ов. Любая очистка требующая новых ресурсов/допускающая отказы, сразу же вызывает тот жуткий код, который Вы напишете в ответ на вопрос из 1-го абзаца


Так этих "самых простых" случаев — 95%, в оставшихся 5-ти используйте обработчики завершения, блоки try catch

Java
r1.open();
try {
  r2.open();//вдруг при инициализации r2 возникнет исключение - надо закрыть r1
  try {
    r3.open();//вдруг при инициализации r3 возникнет исключение - надо закрыть r1 и r2
    try {
      //наконец-то делаем то, что хотели
      ......
    }
    finally {
      r3.close();
    }
  }
  finally {
    r2.close();
  }
}
finally {
  r1.close();
}

ужасно выглядит!

c++
{
  r1.open();
  r2.open();
  r3.open();
  //делаем то, что хотим!!!
  ............
  //метод close автоматически вызовется в деструкторах
}


В с++ в случаях удовлетворяющих идиоме RAII можно использовать деструкторы, в более сложных случах обработчики завершения, блоки try catch
Re[5]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 04.08.08 20:40
Оценка:
Здравствуйте, MasterZiv, Вы писали:

>> Вопрос же "забыть" решается правильным инструментарием в IDE. Кстати,

>> тоже преимущество managed-сред.

MZ>Есть язык программирования, ценность которого заключается в

MZ>том, насколько в нём легко/удобно/правильно и т.п. работать программисту.

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

Например, у J2ME-приложений одни ограничения, правила хорошего тона и приёмы; у J2EE — другие; у Swing'а — третьи. И нормальная IDE позволяет настроить code inspector'ы соответственно окружению.

Более того, даже в рамках одной подплатформы навалом вариаций. Например, нормальная IDE, увидев в качестве target-устройства для J2ME-приложения Motorola iDEN v3.xx, включит дополнительные инспекторы, подсказывающие, что в этой прошивке есть баг, требующий после удаления элемента переоткрытия storage'а. Более того, нормальная IDE сумеет автоматически и корректно зарефакторить Ваш код связанный с этой проблемой...

MZ>Если язык плохой, никакой IDE это не исправит, так что не надо

MZ>мешать мухи с котлетами.

Абсолютно верно. C++ нельзя исправить, уж слишком жуткий синтаксис

MZ>Синтаксис C++ делает практически

>> невозможным реализацию ПО типа ReSharper'а.

MZ>Да думать надо, когда пишешь.


Наоборот! Надо делать так, чтобы не приходилось думать о такой ерунде.

Например, не надо думать о приоритете и порядке исполнения операций в выражении, надо совершенно тупо и без всякого думанья всегда ставить скобки. И тогда SMS-центр не будет лежать все выходные, от того что уставший и задёрганный к концу рабочего дня пятницы (не будем тыкать пальцем ) уже не мог думать какой приоритет у операции "меньше"...
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 04.08.08 21:01
Оценка: +3
Здравствуйте, Vamp, Вы писали:

D>>Ну так и что Вы пишете на C++ в этом случае ?

V>Напишу соответствующий код.

Дык напишите, что Вы стесняетесь

*Так страшненько получается ? А если три вложенных ресурса ?

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

V>Ну и какое же там восстановление возможно? Вот стала у вас система раком и fclose возвращает ошибку. Что делать будете?

Что захочу, то и буду делать. Могу сразу повторить всю операцию, могу поместить запрос на операцию в очередь с приоритетом/уменьшенным таймаутом, могу спросить пользователя "чего делать", могу просто залогировать событие так как мне надо и т.д.

А вот Вы ничего не сможете сделать, бо даже не узнаете о проблеме...
Re[4]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 04.08.08 21:13
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Есть разница, все же, между catch(...) и finally.


Конечно есть.

АШ>catch(...) — я перехватываю все исключения и делаю это сознательно, finally — я попадаю сюда в независимости от того, было ли исключение или нет.


Извиняйте, а кто finally-то написал ? Дед Мороз ? Вы же и написали. И какая Вам нужна была логика, такую и реализовали.

АШ>Так вот, попав в finally по причине исключения я, выбросил SecondExpection, ввожу пользователя в заблуждение, поскольку он получит наведенное исключение, а не первопричину.


Ну так Вы сами себе (и пользователям) злой Буратино. Одно только непонятно, почему бескомпромиссный terminate() Вы считаете более лучшим исходом...
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 04.08.08 21:34
Оценка: +1
Здравствуйте, Аноним, Вы писали:

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


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


Используйте. Получится код а-ля Java, только хуже, бо finally нема.

D>>Итого:


D>>Подход с деструкторами-очистителями в C++ очень сильно ограничен, и нормально покрывает только самые простые (и по-большей части чисто технические) случаи, типа каких-нибудь smart pointer'ов. Любая очистка требующая новых ресурсов/допускающая отказы, сразу же вызывает тот жуткий код, который Вы напишете в ответ на вопрос из 1-го абзаца


А>Так этих "самых простых" случаев — 95%,


В C++ — 95%, бо на smart pointer'ах сидите всяких. А в Java этих случаев 0%, так как никакие припрыгивания с ссылками не нужны.

А> в оставшихся 5-ти используйте обработчики завершения, блоки try catch


См. выше.

А>Java

А>ужасно выглядит!

Да, проблема имеет место быть, в том числе и поэтому, лично я, давно перебрался на .NET
На C# ботва выглядит гораздо симпатичней:

using(var r1 = new R1())
using(var r2 = new R2())
using(var r3 = new R3())
{
   // чего-то делаем
}


А>В с++ в случаях удовлетворяющих идиоме RAII можно использовать деструкторы,


"Ваша доля — 1 лира" (с) адвокат Терезини
Re[9]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Pzz Россия https://github.com/alexpevzner
Дата: 04.08.08 23:42
Оценка: +1
Здравствуйте, shrecher, Вы писали:

Pzz>>Так что в пожирании памяти все же не GC сам ои себе виноват, а чьи-то кривые рученки


S>Я, собственно, ничего не имею против GC. Но с другой стороны, как и любое средство GC вносит сущетвенный overhead в работу программы. В тоже время, использование легковесных уных указателей и деструторов легко заменяют GC для очень большого круга задач.


Обратите внимание, что вумные указатели требуют инкремента счетчика каждый раз, когда вы его значение куда-нибудь передаете, и декремента с проверкой каждый раз, когда оно уже больше не нужно. Причем чтобы работало на SMP-машинке, операции со счетчиком должны быть с memory barrier'ом, что тоже не уменьшает overhead.

С другой стороны, в несколько более высокоуровневых языках, чем C++ (при условии, что компилятор немного больше понимает, что происходит в программе), overhead от GC может случаться только когда кончается память, да и то не во всех случаях.

Поэтому при наличии соответствующей языковой поддержки, система с GC может оказаться даже эффективнее, чем полуручное управления памятью с помощью умных указателей.
Re[6]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Юрий Жмеренецкий ICQ 380412032
Дата: 05.08.08 00:01
Оценка: 6 (3) +1 -2
Здравствуйте, drol, Вы писали:
...
D>И вместо того чтобы дёргать какие-то там деструкторы вне нормального контекста исполнения программы (как поступает C++), managed-языки и -среды предоставляют набор вполне удобных механизмов — try/catch/finally/using — для нормального детерминированного управления объектом.
Где-то я все это уже слышал...

//  C++ 
func() 
{ 
   class_with_possible_ressource  cwpr; 
   dosomethingwith(cwpr); 
} 

//  Java 
func() 
{ 
  class_with_possible_ressource  cwpr = new class_with_possible_ressource; 
  if (cwpr->did_initialise_properly()) 
  { 
     try 
     { 
       dosomethingwith(cwpr); 
     } 
     finally 
     { 
        try 
        { 
           idisp = (IDisposable)cwpr; 
           idisp->Dispose(); 
        } 
        catch (...) 
        { 
        } 
     } 
  } 
}


So the Java func above is as easy to understand as the C++-one?? Come
on — you do not really mean that. Also you have a huge problem writing
generic code in Java .... those ugly and presumably costly runtime
checks have to be made all the time.
(с)peter koch

On Java and C++ comp.lang.java.programmer
Re[6]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: landerhigh Пират  
Дата: 05.08.08 01:42
Оценка:
Здравствуйте, drol, Вы писали:

D>Наоборот! Надо делать так, чтобы не приходилось думать о такой ерунде.

D>Например, не надо думать о приоритете и порядке исполнения операций в выражении, надо совершенно тупо и без всякого думанья всегда ставить скобки. И тогда SMS-центр не будет лежать все выходные, от того что уставший и задёрганный к концу рабочего дня пятницы (не будем тыкать пальцем ) уже не мог думать какой приоритет у операции "меньше"...
Безотносительно языка программирования, нужно писать юнит-тесты. Чтобы не уповать на среду, на синтаксис и скобки и чтобы ничего не лежало из-за того, что кто-то прошляпил приоритет операций.
Re[6]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: MasterZiv СССР  
Дата: 05.08.08 05:31
Оценка: 3 (1) +1
drol пишет:

> MZ>Да думать надо, когда пишешь.

>
> Наоборот! Надо делать так, чтобы *не приходилось думать о такой ерунде*.
>
> Например, *не надо думать* о приоритете и порядке исполнения операций в
> выражении, надо совершенно тупо и без всякого думанья *всегда ставить
> скобки*. И тогда SMS-центр не будет лежать все выходные, от того что

Для того, чтобы не надо было думать, это всё должно быть в языке, а не
в каком-то редакторе. У редактора нет ни спецификации, ни стандарта,
есть только надежда, что он как-то поможет.

Но я бы даже сказал больше, что не думать вообще очень вредно.
НАДО ДУМАТЬ ! И надо иметь красивый сложный и мощный язык.

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

Я думаю, что тему надо прекратить, агитировать С++-ников за то,
какая хорошая Java — бессмысленно, а на изначально поставленные
вопросы уже ответили.
Posted via RSDN NNTP Server 2.1 beta
Re[10]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Danchik Украина  
Дата: 05.08.08 05:41
Оценка: :))) :))
Здравствуйте, Pzz, Вы писали:

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


Pzz>>>Так что в пожирании памяти все же не GC сам ои себе виноват, а чьи-то кривые рученки


S>>Я, собственно, ничего не имею против GC. Но с другой стороны, как и любое средство GC вносит сущетвенный overhead в работу программы. В тоже время, использование легковесных уных указателей и деструторов легко заменяют GC для очень большого круга задач.


Pzz>Обратите внимание, что вумные указатели требуют инкремента счетчика каждый раз, когда вы его значение куда-нибудь передаете, и декремента с проверкой каждый раз, когда оно уже больше не нужно. Причем чтобы работало на SMP-машинке, операции со счетчиком должны быть с memory barrier'ом, что тоже не уменьшает overhead.


Pzz>С другой стороны, в несколько более высокоуровневых языках, чем C++ (при условии, что компилятор немного больше понимает, что происходит в программе), overhead от GC может случаться только когда кончается память, да и то не во всех случаях.


Pzz>Поэтому при наличии соответствующей языковой поддержки, система с GC может оказаться даже эффективнее, чем полуручное управления памятью с помощью умных указателей.


Что то я сомневаюсь что managed языки не используют подсчет ссылок для определения свободен ли обьект или нет для освобождения через GC. Есть другие мнения?
Re[10]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: shrecher  
Дата: 05.08.08 06:58
Оценка: -1
Здравствуйте, Pzz, Вы писали:


Pzz>Причем чтобы работало на SMP-машинке, операции со счетчиком должны быть с memory barrier'ом, что тоже не уменьшает overhead.


Для этого используется обычный InterlockedDecrement, который реализован аппаратно через префикс lock для декремнта:

lock dec eax


В итоге, операции со счетчиком ссылок занимают пару ассемблерных инструкций.
Re[11]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 05.08.08 07:29
Оценка:
Здравствуйте, shrecher, Вы писали:

S>Для этого используется обычный InterlockedDecrement, который реализован аппаратно через префикс lock для декремнта:


S>
S>lock dec eax
S>

Сильно!

int InterlockedDecrement (int *value)
{
    __asm
    {
        mov    ecx, DWORD ptr [value]
        mov    eax, -1
        lock xadd DWORD ptr [ecx],eax
        dec    eax
    }
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[12]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: shrecher  
Дата: 05.08.08 07:41
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC> Сильно!


Не понял, что вас так сильно развеселило?
Re[13]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 05.08.08 08:15
Оценка:
Здравствуйте, shrecher, Вы писали:

S>Не понял, что вас так сильно развеселило?

то, что залоченная операция проводится с регистром а не с памятью.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[14]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: shrecher  
Дата: 05.08.08 08:28
Оценка:
Здравствуйте, CreatorCray, Вы писали:

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


S>>Не понял, что вас так сильно развеселило?

CC>то, что залоченная операция проводится с регистром а не с памятью.

Это к вопросу не относится. На самом деле, я хотел сказать, что overhead от memory barrier и подщета счетчика ссылок минимальный.
Re[15]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 05.08.08 10:28
Оценка:
Здравствуйте, shrecher, Вы писали:

S>я хотел сказать, что overhead от memory barrier и подщета счетчика ссылок минимальный.

Оверхед от барьера на самом деле относительно существенный.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[11]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: nikov США http://www.linkedin.com/in/nikov
Дата: 05.08.08 12:34
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Что то я сомневаюсь что managed языки не используют подсчет ссылок для определения свободен ли обьект или нет для освобождения через GC. Есть другие мнения?


.NET не использует подсчет ссылок. Он строит граф достижимых объектов, остальные автоматически умирают при дефрагментации.
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: SE Украина  
Дата: 05.08.08 13:18
Оценка:
Здравствуйте, shrecher, Вы писали:

Прошу прощения, но пара замечаний из мира .NET

S>GC не оптимально расходует память. К примеру, если создал 10 м объектов, но используешь только 100, а остальные уже не надо бы держать в мозгах и их уже можно разрушить, но вся эта куча объектов не может быть удалена автоматически, если неизвесна семантика твоей программы.


Семантика тут не при чем. В дотнете GC работает следующим образом: нет больше ссылок на объект (включая и стек комманд, замечу), всё — объект готов к удалению сборщиком мусора.

S>Поэтому и получается, что программы на Java столько памяти и кушают.


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

Про деструкторы. В той же спецификации С# так прямо и написано — по возможности не используйте деструкторы.
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 05.08.08 13:19
Оценка: 1 (1) +2 -1
Здравствуйте, landerhigh, Вы писали:

L>Безотносительно языка программирования, нужно писать юнит-тесты.


Относительно-относительно. Писать unit-тесты для C++ — тот ещё экстрим. Reflection'а нет, невозможен нормальный mock'инг, всё копи-пастом, да жуткими макросами всякими, с нулевым maintainability в результате.

L>Чтобы не уповать на среду, на синтаксис и скобки и чтобы ничего не лежало из-за того,


Уповать не надо ни на что. Однако все, всё и вся в разработке должны помогать избегать ошибок. И язык, и IDE, и unit-тесты, и своя голова, и коллеги, и QA. И чем больше таких возможностей предоставляют нижние уровни иерархии, тем меньше проблем всплывёт в "день "Ч".

L>что кто-то прошляпил приоритет операций.


Пример же с приоритетами показывает, что элементарное поведение позволяет полностью ликвидировать целый класс ошибок ещё на самом первом уровне. И, что не менее важно, с нулевыми затратами на "думанье".
Re[13]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Mamut Швеция http://dmitriid.com
Дата: 05.08.08 15:01
Оценка:
C>Да ну нах, что за чушь.
C>Соберите объектник слинкуйте и запустите хоть где нибудь без Java интерпретатора в кучу мегов
C>Так что не надо передергивать и всякие там байт коды называть бинарниками ок?

соберите объектник и запустите его где-нибдь без mcvcrt*.dll, crt.dll и прочих


dmitriid.comGitHubLinkedIn
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Mamut Швеция http://dmitriid.com
Дата: 05.08.08 15:10
Оценка: +1
ЮЖ>Где-то я все это уже слышал...
ЮЖ>

ЮЖ>//  C++ 
ЮЖ>func() 
ЮЖ>{ 
ЮЖ>   class_with_possible_ressource  cwpr; 
ЮЖ>   dosomethingwith(cwpr); 
ЮЖ>} 

ЮЖ>//  Java 
ЮЖ>func() 
ЮЖ>{ 
ЮЖ>  class_with_possible_ressource  cwpr = new class_with_possible_ressource; 
ЮЖ>  if (cwpr->did_initialise_properly()) 
ЮЖ>  { 

ЮЖ>


Разве в С++ не требуется проверки, правильно инициализировался объект или нет?


dmitriid.comGitHubLinkedIn
Re[8]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Vamp Россия  
Дата: 05.08.08 15:11
Оценка: +1
M>Разве в С++ не требуется проверки, правильно инициализировался объект или нет?
Зависит от архитектуры класса. Можно просто исключение кинуть из конструктора. И тогда !ЧУДО! деструкторы всех уже сконструированных членов автоматически позовутся. Безо всяких catch-finally вообще!
Да здравствует мыло душистое и веревка пушистая.
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Mamut Швеция http://dmitriid.com
Дата: 05.08.08 15:14
Оценка:
Здравствуйте, Аноним, Вы писали:

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


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


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


D>>Итого:


D>>Подход с деструкторами-очистителями в C++ очень сильно ограничен, и нормально покрывает только самые простые (и по-большей части чисто технические) случаи, типа каких-нибудь smart pointer'ов. Любая очистка требующая новых ресурсов/допускающая отказы, сразу же вызывает тот жуткий код, который Вы напишете в ответ на вопрос из 1-го абзаца


А>Так этих "самых простых" случаев — 95%, в оставшихся 5-ти используйте обработчики завершения, блоки try catch


А>Java

А>
А>r1.open();
А>try {
А>  r2.open();//вдруг при инициализации r2 возникнет исключение - надо закрыть r1
А>  try {
А>    r3.open();//вдруг при инициализации r3 возникнет исключение - надо закрыть r1 и r2
А>    try {
А>      //наконец-то делаем то, что хотели
А>      ......
А>    }
А>    finally {
А>      r3.close();
А>    }
А>  }
А>  finally {
А>    r2.close();
А>  }
А>}
А>finally {
А>  r1.close();
А>}
А>

А>ужасно выглядит!

А>c++

А>
А>{
А>  r1.open();
А>  r2.open();
А>  r3.open();
А>  //делаем то, что хотим!!!
А>  ............
А>  //метод close автоматически вызовется в деструкторах
А>}
А>


А что, при инициализации r1, r2, r3 в С++ не может возникнуть исключений? Если приводить код, то, может, будем его одинаковым приводить?


dmitriid.comGitHubLinkedIn
Re[9]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Mamut Швеция http://dmitriid.com
Дата: 05.08.08 15:18
Оценка:
M>>Разве в С++ не требуется проверки, правильно инициализировался объект или нет?
V>Зависит от архитектуры класса. Можно просто исключение кинуть из конструктора. И тогда !ЧУДО! деструкторы всех уже сконструированных членов автоматически позовутся. Безо всяких catch-finally вообще!

А разве в Яве не так же? И вообще приведенный код не равнозначен, имхо.


dmitriid.comGitHubLinkedIn
Re[10]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Vamp Россия  
Дата: 05.08.08 15:20
Оценка: +1
M>А разве в Яве не так же? И вообще приведенный код не равнозначен, имхо.
В Яве разве вообще есть понятие автоматически вызываемого деструктора?
Да здравствует мыло душистое и веревка пушистая.
Re[9]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 05.08.08 16:08
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Можно просто исключение кинуть из конструктора. И тогда !ЧУДО! деструкторы всех уже сконструированных членов автоматически позовутся. Безо всяких catch-finally вообще!


Ага. А если эти самые деструкторы тоже начнут кидать исключения, то мы тут же получим чудо-terminate()
Re[10]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Vamp Россия  
Дата: 05.08.08 16:10
Оценка:
D>Ага. А если эти самые деструкторы тоже начнут кидать исключения, то мы тут же получим чудо-terminate()
Уже обсуждали. Не начнут.
Да здравствует мыло душистое и веревка пушистая.
Re[8]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 05.08.08 16:13
Оценка:
Здравствуйте, Mamut, Вы писали:

M>А что, при инициализации r1, r2, r3 в С++ не может возникнуть исключений? Если приводить код, то, может, будем его одинаковым приводить?


Да ладно. Не придирайтесь Что имел ввиду автор — вполне понятно.
Re[15]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: WolfHound  
Дата: 05.08.08 17:18
Оценка:
Здравствуйте, shrecher, Вы писали:

S>Это к вопросу не относится. На самом деле, я хотел сказать, что overhead от memory barrier и подщета счетчика ссылок минимальный.

Сотня тактов. Подумаешь фигня какая...
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[8]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: WolfHound  
Дата: 05.08.08 17:19
Оценка:
Здравствуйте, SE, Вы писали:

SE>Про деструкторы. В той же спецификации С# так прямо и написано — по возможности не используйте деструкторы.

В C# нет деструкторов.
Там есть финалайзеры. Это совсем другое.
Еще там есть костыль ака IDisposable который применяется для заменя деструкторов когда нужна детерминированная финализация.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[8]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.08.08 17:21
Оценка:
Здравствуйте, Mamut, Вы писали:

M>А что, при инициализации r1, r2, r3 в С++ не может возникнуть исключений? Если приводить код, то, может, будем его одинаковым приводить?


Если в С++ при вызове r2.open() возникнет исключение, то деструктор r1 выполнит все действия по очистке, т.е. r1.close() вызывать не нужно. Так что код выглядит одинаковым.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[11]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 05.08.08 18:00
Оценка: -2
Здравствуйте, Vamp, Вы писали:

D>>Ага. А если эти самые деструкторы тоже начнут кидать исключения, то мы тут же получим чудо-terminate()

V>Уже обсуждали.

Обсуждали. Но в свете "!ЧУДО!...Безо всяких catch-finally вообще!", видимо осознание ещё неполно

V>Не начнут.


Так вот. Как мы установили выше по треду, в связи с ограничениями на содержимое, деструкторы C++ могут являться реализацией концепции "очистителя ресурсов" в основном только для чисто технических вещей а-ля smart pointer'ы. А так как Java не нуждается в оных мутантах, то оверхэда в виде try/catch/finally аналогичный java-код содержать не будет. Более того, во всех остальных ситуациях преимущество на стороне managed-языков, так как они располагают try/finally, а на C++ придётся плясать исключительно с try/catch...

*Когда код-то напишете ?
Re[9]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 05.08.08 18:20
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>В C# нет деструкторов.

WH>Там есть финалайзеры. Это совсем другое.

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

Так что не финалайзеры "это совсем другое", а менеджеры памяти C++ и .NET отличаются

WH>Еще там есть костыль ака IDisposable который применяется для заменя деструкторов когда нужна детерминированная финализация.


И исходя из вышесказанного, IDisposable никоим образом не может применяться для замены деструкторов
Re[10]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: fmiracle  
Дата: 05.08.08 19:11
Оценка:
Здравствуйте, drol, Вы писали:

D>А вот на мой взгляд, финалайзеры вполне себе деструкторы. Также запускаются из внутреннего контекста менеджера памяти, создавая возможность для нездорового поведения. Также сильно ограничены в содержимом. И даже механизмы вызова практически идентичен, бо дёргаются менеджером памяти в процессе освобождения этой самой памяти.


Хотя (насколько я помню) стандарт С++ и не определяет точного момента вызова деструктора, но все же это где-то в районе выхода из блока/метода.

В С# финалайзер вызывается при следующей сборке мусора данного поколения. А это может быть и через 2 миллисикунды, и через два дня и через 2 недели — зависит от использования. Закрыть соединение с базой "послезавтра" — не ахти как результат.
Т.е. финалайзер это нужная и полезная вещь, но это последний рубеж обороны и не заменяет явного освобождения ресурсов.
Re[11]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: fmiracle  
Дата: 05.08.08 19:15
Оценка: +1
Здравствуйте, codelord, Вы писали:

C>Только вот когда дело касается эффективности, то все эти штучки дрючки на ( ...-машинах )

C>нервно курят ( лучше со-ут ). И разные это вещи каждому свое которые не корректно сравнивать ( С++ компилируемый язык, точка ). Мне нравится когда код работает с максимальной эффективностью очень быстро.
C>и это не для интерпретаторов на ( ...-машинах )

Ха! А Java — дваждыкомпилируемый язык, она круче!
А с hotspot — вообще многократно рекомпилируемый!!


З.Ы. А если серьезно — изучи вопрос. Джава — компилируемый язык, только окончательная компиляция в машкоды происходит в процессе работы приложения.
Re[13]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 05.08.08 19:27
Оценка:
Здравствуйте, codelord, Вы писали:

C>Да ну нах, что за чушь.

C>Соберите объектник слинкуйте и запустите хоть где нибудь без Java интерпретатора в кучу мегов
Excelsior JET. Минимальное приложение (в виде автономного exe-шника) на Java — около 500Кб. Минимальное приложение с GUI (SWT) — около мегабайта.

Что я делаю не так?
Sapienti sat!
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 05.08.08 19:43
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

D>>И вместо того чтобы дёргать какие-то там деструкторы вне нормального контекста исполнения программы (как поступает C++), managed-языки и -среды предоставляют набор вполне удобных механизмов — try/catch/finally/using — для нормального детерминированного управления объектом.


ЮЖ>Где-то я все это уже слышал...


Давайте проверим Вашу память.

Итак, что же тут понаписал peter koch... Похоже пытался портировать свой код на Java. А так как, насколько я могу судить по этому фрагменту, толком ни Java, ни С++ не знает, то получилась, разумеется, ерунда.

Возник какой-то did_initialise_properly(), тогда как никаких проблем захватить ресурс в конструкторе, аналогично C++ оригиналу, нет.
Куда-то потеряли terminate(), который, скорее всего, случится если деструктор class_with_possible_ressource бросит исключение.

Итого, правильный прямой порт:

void func() 
{
  class_with_possible_ressource cwpr = new class_with_possible_ressource();
  try
  {
       dosomethingwith(cwpr);
  }
  finally
  {
     if (cwpr instanceof Closeable) {
       try {
          ((Closeable)cwpr).close();
       } catch {
          terminate();
       }
     }
  }
}


Теперь рассмотрим нормальный порт, в стиле действительно Java, где не боятся исключений:

void func() 
{
  class_with_possible_ressource cwpr = new class_with_possible_ressource();
  try
  {
       dosomethingwith(cwpr);
  }
  finally
  {
     if (cwpr instanceof Closeable) {
       ((Closeable)cwpr).close();
     }
  }
}


*В большинстве случаев даже кастить не надо будет, интерфейс обычно явно сразу поддерживается... Ну да ладно...

А как будет выглядеть аналог на C++, да в свете выводов о реальной нише деструкторов http://www.rsdn.ru/forum/message/3047345.1.aspx
Автор: drol
Дата: 04.08.08

и http://www.rsdn.ru/forum/message/3048703.aspx
Автор: drol
Дата: 05.08.08
?

Ну и напоследок, я всё-таки соглашусь с koch'ом: в Java сделано неудобно И посему C# рулит

void func() 
{
  using(var cwpr = new class_with_possible_ressource()) 
    dosomethingwith(cwpr);
}
Re[9]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: SE Украина  
Дата: 05.08.08 20:18
Оценка:
Здравствуйте, WolfHound, Вы писали:

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


WH>В C# нет деструкторов.

WH>Там есть финалайзеры. Это совсем другое.

Так, а вот тут поподробней.
Вот что первое на глаза попалось: С# 3.0 Specification

1.6.7.6 Destructors
A destructor is a member that implements the actions required to destruct an instance of a class. Destructors cannot have parameters, they cannot have accessibility modifiers, and they cannot be invoked explicitly. The destructor for an instance is invoked automatically during garbage collection.
The garbage collector is allowed wide latitude in deciding when to collect objects and run destructors. Specifically, the timing of destructor invocations is not deterministic, and destructors may be executed on any thread. For these and other reasons, classes should implement destructors only when no other solutions are feasible.
The using statement provides a better approach to object destruction.


И это только один абзац. А вот слово Finalizer не было найдено ни разу, кроме как часть имени функции. Так что в С# надо говорить — деструкторы. А вот в CLR таки да это же самое обозвано финалайзерами

WH>Еще там есть костыль ака IDisposable который применяется для заменя деструкторов когда нужна детерминированная финализация.

Да, костыль, но зато какой удобный

P.S. Я не нудный, я — скрупулезный
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 05.08.08 20:18
Оценка:
Здравствуйте, MasterZiv, Вы писали:

>> MZ>Да думать надо, когда пишешь.


>> Наоборот! Надо делать так, чтобы *не приходилось думать о такой ерунде*.


MZ>Для того, чтобы не надо было думать, это всё должно быть в языке, а не

MZ>в каком-то редакторе. У редактора нет ни спецификации, ни стандарта,

Вы совершенно правы. У редактора, Word'а например, действительно ничего нет. Но зачем Вы пишете программы в Word'е ??? Это ведь страшно неудобно Программы надо разрабатывать в нормальных IDE, которые и спецификации, и стандарт отлично знают.

MZ>Но я бы даже сказал больше, что не думать вообще очень вредно.


А я Вам ещё раз повторю: о всякой ерунде думать не надо.

MZ>НАДО ДУМАТЬ !


Да, думать надо. Думать об архитектуре, о дизайне, о usability и т.д. А вот о приоритетах операций думать не надо. Более того, надо стараться, чтобы не требовалось думать о как можно большем количестве вещей. Например, возвращаясь к теме топика, о костылях из smart pointer'ов...

MZ>И надо иметь красивый сложный и мощный язык.


Свят-свят-свят... Надо иметь простой, удобный, выразительный, и в тоже время строгий язык. А ещё лучше несколько языков для единого managed runtime'а. Бо задачи бывают сильно и сильно разные.

MZ>А если человек не в состоянии уяснить приоритет операций в языке,


Вы обижаете (не будем тыкать пальцем ). Он профессионал (и, скорее всего, сильно поболее Вас). Просто был очень уставший...

MZ>на котором он программирует, или хотя бы заглянуть в справочник

MZ>в сложных случаях,

Зачем ? Скобки решают проблему автоматически и без всяких заглядываний.

MZ>его надо увольнять на фиг.


Гы! Да он Вас сам уволит на раз

MZ>Я думаю, что тему надо прекратить, агитировать С++-ников за то,

MZ>какая хорошая Java — бессмысленно,

Вы меня обижаете. Я правоверный .NET-чик, как я могу агитировать в пользу застрявшей в каменном веке Java ???

MZ>а на изначально поставленные

MZ>вопросы уже ответили.

В принципе — да. Однако ещё не все участники дискуссии осознали всю глубину ответов
Re[10]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: nikov США http://www.linkedin.com/in/nikov
Дата: 05.08.08 20:32
Оценка: 4 (1)
Здравствуйте, SE, Вы писали:


SE>Вот что первое на глаза попалось: С# 3.0 Specification


SE>

SE>1.6.7.6 Destructors


Да, сначала называлось так, потом переименовали в finalizer и стандартизировали в Ecma-334. В C# 3.0 произошла регрессия к destructor, но процесс стандартизации эта версия спецификации еще не прошла.
Re[14]: оффтоп
От: frogkiller Россия  
Дата: 05.08.08 20:45
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>>Соберите объектник слинкуйте и запустите хоть где нибудь без Java интерпретатора в кучу мегов

C>Excelsior JET. Минимальное приложение (в виде автономного exe-шника) на Java — около 500Кб. Минимальное приложение с GUI (SWT) — около мегабайта.

И это, по-твоему, маленький размер? А, ну да, в 640к помещается
Печально, это на самом деле.
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[8]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Adriano  
Дата: 06.08.08 01:28
Оценка:
Здравствуйте, Mamut, Вы писали:

M>Здравствуйте, Аноним, Вы писали:


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


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


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


D>>>Итого:


D>>>Подход с деструкторами-очистителями в C++ очень сильно ограничен, и нормально покрывает только самые простые (и по-большей части чисто технические) случаи, типа каких-нибудь smart pointer'ов. Любая очистка требующая новых ресурсов/допускающая отказы, сразу же вызывает тот жуткий код, который Вы напишете в ответ на вопрос из 1-го абзаца


А>>Так этих "самых простых" случаев — 95%, в оставшихся 5-ти используйте обработчики завершения, блоки try catch


А>>Java

А>>
А>>r1.open();
А>>try {
А>>  r2.open();//вдруг при инициализации r2 возникнет исключение - надо закрыть r1
А>>  try {
А>>    r3.open();//вдруг при инициализации r3 возникнет исключение - надо закрыть r1 и r2
А>>    try {
А>>      //наконец-то делаем то, что хотели
А>>      ......
А>>    }
А>>    finally {
А>>      r3.close();
А>>    }
А>>  }
А>>  finally {
А>>    r2.close();
А>>  }
А>>}
А>>finally {
А>>  r1.close();
А>>}
А>>

А>>ужасно выглядит!

А>>c++

А>>
А>>{
А>>  r1.open();
А>>  r2.open();
А>>  r3.open();
А>>  //делаем то, что хотим!!!
А>>  ............
А>>  //метод close автоматически вызовется в деструкторах
А>>}
А>>


M>А что, при инициализации r1, r2, r3 в С++ не может возникнуть исключений? Если приводить код, то, может, будем его одинаковым приводить?


да, могу возникнуть, и возникнут! но это нас не касается
читайте здесь
Автор: jazzer
Дата: 04.08.08
Re[15]: оффтоп
От: Cyberax Марс  
Дата: 06.08.08 01:31
Оценка:
Здравствуйте, frogkiller, Вы писали:

C>>>Соберите объектник слинкуйте и запустите хоть где нибудь без Java интерпретатора в кучу мегов

C>>Excelsior JET. Минимальное приложение (в виде автономного exe-шника) на Java — около 500Кб. Минимальное приложение с GUI (SWT) — около мегабайта.
F>И это, по-твоему, маленький размер? А, ну да, в 640к помещается
Если учесть, что туда ещё упакован GC и достаточно много утиллитных классов — то совсем неплохо.

С Java/.NET проблема как раз в том, что для минимального приложения получается очень большой оверхед. На больших приложениях этот оверхед не заметен.

F>Печально, это на самом деле.

Не, нормально.
Sapienti sat!
Re[8]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: landerhigh Пират  
Дата: 06.08.08 01:54
Оценка: +2
Здравствуйте, drol, Вы писали:

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


L>>Безотносительно языка программирования, нужно писать юнит-тесты.


D>Относительно-относительно. Писать unit-тесты для C++ — тот ещё экстрим. Reflection'а нет, невозможен нормальный mock'инг, всё копи-пастом, да жуткими макросами всякими, с нулевым maintainability в результате.

(Смотрит в код). Слушайте, ну это просто праздник какой-то! В моем личном списке оправданий отстутсвия юнит-тестов конкретно это займет первое место надолго. Оказывается, отсутствие рефлектора мешает писать юнит-тесты! И правда, как же мы, бедные, мучаемся? У нас даже ни копи-паста, ни жутких макросов не получается, наверное, что-то делаем в корне неправильно.
На втором месте в списке оправданий навечно поселилось незабвенное "Нам код писать надо, некогда ерундой занматься". Кстати, услышано от одних жавистов. У них, видать, тоже рефлекшена не было.
Мы пишем юнит-тесты на С++. Отсутствие рефлекшена нам почему-то не мешает.
L>>Чтобы не уповать на среду, на синтаксис и скобки и чтобы ничего не лежало из-за того,
D>Уповать не надо ни на что. Однако все, всё и вся в разработке должны помогать избегать ошибок. И язык, и IDE, и unit-тесты, и своя голова, и коллеги, и QA. И чем больше таких возможностей предоставляют нижние уровни иерархии, тем меньше проблем всплывёт в "день "Ч".
Ну вот своя голова прошляпила приоритет. Как в этом случае поможет езыг или IDE?
D>Пример же с приоритетами показывает, что элементарное поведение позволяет полностью ликвидировать целый класс ошибок ещё на самом первом уровне. И, что не менее важно, с нулевыми затратами на "думанье".
Пример с приоритетами показывает, что человеку свойственно ошибаться. Ну подсказала среда в простом случае, но в сложном она умывает руки. Можно бесконечно обосновывать невозможность покрытия тестом сферического кода в вакууме, но опыт показывает, что простейшие тесты на проверку редко возникающих условий позволяют помочь найти ошибку задолго до того, как совершивший ее получит по башке.
Среда же лишь может подсказать в элементарных случаях, думать она не обучена. В сложных случаях оно не только не поможет, но еще и навредить может.
Вот у меня есть конструкции вида (эстетам просьба не беспокоиться, у нас все продумано и такое использование оправдано)
MyClass::MyClass():
myMember(this)
{}

На которые компилятор кричит-кричит, аж надрывается, бедный. Так это я и без него знаю, что это может быть опасно в определенных случаях, но я также знаю, что это вовсе не тот случай. А компилятор не знает. Приходится его успокаивать прагмой.
Re[8]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: landerhigh Пират  
Дата: 06.08.08 02:00
Оценка: 8 (1)
Здравствуйте, drol, Вы писали:

MZ>>НАДО ДУМАТЬ !

D>Да, думать надо. Думать об архитектуре, о дизайне, о usability и т.д. А вот о приоритетах операций думать не надо. Более того, надо стараться, чтобы не требовалось думать о как можно большем количестве вещей. Например, возвращаясь к теме топика, о костылях из smart pointer'ов...
Абсолютно верно. Вот я 80% времени при разработке думаю об архитектуре, дизайне и, самое главное, о юзабилити. А о приоритетах операций, равно как и о смарт поинтерах и "жутких проблемах, связанных с ручным управлением памятью" вообще никогда не думаю. Потому что этих проблем попросту не существует.

Даже подумалось — если для кого-то "приоритет операций" вырастает в проблему, то может, этому "кому-то" следует задуматься о смене рода деятельности?

ЗЫ — пишу на C++ и C#. Устриц тоже ем регулярно.
Re[8]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: landerhigh Пират  
Дата: 06.08.08 02:05
Оценка:
Здравствуйте, drol, Вы писали:

D>Ну и напоследок, я всё-таки соглашусь с koch'ом: в Java сделано неудобно И посему C# рулит


D>
D>void func() 
D>{
D>  using(var cwpr = new class_with_possible_ressource()) 
D>    dosomethingwith(cwpr);
D>}
D>


С++

void func()
{
     dosomethingwith(class_with_possible_ressource());
}


Re[12]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: PaulMinelly  
Дата: 06.08.08 05:30
Оценка:
Здравствуйте, nikov, Вы писали:

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


D>>Что то я сомневаюсь что managed языки не используют подсчет ссылок для определения свободен ли обьект или нет для освобождения через GC. Есть другие мнения?


N>.NET не использует подсчет ссылок. Он строит граф достижимых объектов, остальные автоматически умирают при дефрагментации.


Ну и что это не подсчет ссылок, если ссылок 1 (одна) то объект оставить — если 0, то finalize. Формально, очень даже подсчет ссылок.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[13]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: nikov США http://www.linkedin.com/in/nikov
Дата: 06.08.08 07:04
Оценка: +4 -1
Здравствуйте, PaulMinelly, Вы писали:

N>>.NET не использует подсчет ссылок. Он строит граф достижимых объектов, остальные автоматически умирают при дефрагментации.


PM>Ну и что это не подсчет ссылок, если ссылок 1 (одна) то объект оставить — если 0, то finalize. Формально, очень даже подсчет ссылок.


И все таки, обычно подсчетом ссылок называется другой механизм.
Re[12]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: codelord  
Дата: 06.08.08 07:21
Оценка: -10 :))
Для таких как ты любителей передергивать, я написал что имел ввиду получение исполняемого файла,
и если серьезно когда человек за словами не видит смысла, это признак дебильности, честно посмотри в литературу.
А то что ты называешь компиляцией является только способом получения суррогата в виде байт-кода, который твоя
... машина берется интерпретировать и исполнять.

F>З.Ы. А если серьезно — изучи вопрос. Джава — компилируемый язык, только окончательная компиляция в машкоды происходит в процессе работы приложения.


Сообщение отредактировано модератором. ДХ
Re[14]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: codelord  
Дата: 06.08.08 07:22
Оценка:
Ты видимо собираешь некоторый огрызок. который ни то ни другое
Здравствуйте, Cyberax, Вы писали:

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


C>>Да ну нах, что за чушь.

C>>Соберите объектник слинкуйте и запустите хоть где нибудь без Java интерпретатора в кучу мегов
C>Excelsior JET. Минимальное приложение (в виде автономного exe-шника) на Java — около 500Кб. Минимальное приложение с GUI (SWT) — около мегабайта.

C>Что я делаю не так?
Re[16]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: shrecher  
Дата: 06.08.08 07:23
Оценка: -2
Здравствуйте, WolfHound, Вы писали:

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


S>>Это к вопросу не относится. На самом деле, я хотел сказать, что overhead от memory barrier и подщета счетчика ссылок минимальный.

WH>Сотня тактов. Подумаешь фигня какая...

Ты имел ввиду эти четыре ассемблерные инструкции на инеремент или декремент счетчика?! Это действительно фигня. Вызов функуции с парой агрументов занимает больще времени. Смысла нет экономить на этих "спичках".
Re[14]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 06.08.08 08:53
Оценка:
Здравствуйте, Mamut, Вы писали:

M>соберите объектник и запустите его где-нибдь без mcvcrt*.dll, crt.dll и прочих

хехе.
мои почти все будут работать
им из DLL тока kernel + gdi надо.
все остальное: static linking
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[16]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 06.08.08 08:53
Оценка:
Здравствуйте, WolfHound, Вы писали:

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


S>>Это к вопросу не относится. На самом деле, я хотел сказать, что overhead от memory barrier и подщета счетчика ссылок минимальный.

WH>Сотня тактов. Подумаешь фигня какая...
в среднем бывает около трех сотен
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[17]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 06.08.08 08:53
Оценка:
Здравствуйте, shrecher, Вы писали:

S>Ты имел ввиду эти четыре ассемблерные инструкции на инеремент или декремент счетчика?! Это действительно фигня.

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

S>Вызов функуции с парой агрументов занимает больще времени. Смысла нет экономить на этих "спичках".

да ну?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[14]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: codelord  
Дата: 06.08.08 09:55
Оценка: -2
M>соберите объектник и запустите его где-нибдь без mcvcrt*.dll, crt.dll и прочих

во первых таких либ у меня нет я пишу под Linux,
во вторых если вы имеете ввиду системные либы, то без них никто не работает
в т/ч и ваша ява. И еще если очень хочется то можно, вам знакомо понятие статическая линковка?
( хотя с явой врятли )

Сообщение отредактировано модератором. ДХ
Re[15]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Mamut Швеция http://dmitriid.com
Дата: 06.08.08 10:07
Оценка: -1
C>Вот еще один умник, во первых таких либ у меня нет
C>я пишу под Linux, во вторых если вы имеете ввиду системные либы, то без них никто не работает
C>в т/ч и ваша ява. И еще если очень хочется то можно, вам знакомо понятие статическая линковка?
C>( хотя с явой врятли )

JVM — это системные либы для приложений на Яве

ЗЫ. Мне всегда интересно наблюдать, как делаются далекоидущие выводы на основе только одного сообщения собеседника.


dmitriid.comGitHubLinkedIn
Re[11]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Mamut Швеция http://dmitriid.com
Дата: 06.08.08 10:10
Оценка:
M>>А разве в Яве не так же? И вообще приведенный код не равнозначен, имхо.
V>В Яве разве вообще есть понятие автоматически вызываемого деструктора?

Хз

Насчет того, что код неравнозначен я имею в виду, что:
— для Явы почему-то понадобилось проверять, инициализировался ли объект. С++ же не дает такую гарантию
— для С++ почему-то считается, что dosomethingwith(cwpr) не выкинет нигде никаких исключений

Код будет равнозхначен только с приведенным кодом dosomethingwith и class_with_possible_ressource


dmitriid.comGitHubLinkedIn
Re[9]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Mamut Швеция http://dmitriid.com
Дата: 06.08.08 10:11
Оценка:
M>>А что, при инициализации r1, r2, r3 в С++ не может возникнуть исключений? Если приводить код, то, может, будем его одинаковым приводить?

E>Если в С++ при вызове r2.open() возникнет исключение, то деструктор r1 выполнит все действия по очистке, т.е. r1.close() вызывать не нужно. Так что код выглядит одинаковым.


Мде. Позабыл я С++, оказывается


dmitriid.comGitHubLinkedIn
Re[16]: оффтоп
От: frogkiller Россия  
Дата: 06.08.08 10:22
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>С Java/.NET проблема как раз в том, что для минимального приложения получается очень большой оверхед. На больших приложениях этот оверхед не заметен.


Именно поэтому, я и печалюсь Получается, что индустрия подталкивает (даже не подталкивает, а тащит с громадной силой) к написанию больших приложений — даже там, где можно обойтись гораздо меньшими усилиями.
Курица — это инструмент, с помощью которого одно яйцо производит другие.
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: WolfHound  
Дата: 06.08.08 10:48
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>НАДО ДУМАТЬ ! И надо иметь красивый сложный и мощный язык.

Вот и подумай зачем языку быть сложным?
И если ты любишь сложность то эти языки для тебя. Уверен тебе понравится.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[9]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: drol  
Дата: 06.08.08 11:17
Оценка:
Здравствуйте, landerhigh, Вы писали:

D>>
D>>void func() 
D>>{
D>>  using(var cwpr = new class_with_possible_ressource()) 
D>>    dosomethingwith(cwpr);
D>>}
D>>


L>С++


L>
L>void func()
L>{
L>     dosomethingwith(class_with_possible_ressource());
L>}
L>


Неэквивалентно, бо terminate() после исключений из деструкторов, тогда как в C# никаких проблем.
Re[13]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: fmiracle  
Дата: 06.08.08 11:34
Оценка: +2 -1
Здравствуйте, codelord, Вы писали:

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

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

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

Например то, что байт-код перед исполнением компилируется в машинные коды, в отличии от интерпретируемых языков.
Re[10]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: landerhigh Пират  
Дата: 06.08.08 11:43
Оценка: +1
Здравствуйте, drol, Вы писали:

L>>
L>>void func()
L>>{
L>>     dosomethingwith(class_with_possible_ressource());
L>>}
L>>


D>Неэквивалентно, бо terminate() после исключений из деструкторов, тогда как в C# никаких проблем.


Исключения из деструкторов бывают только в случае кривого драйвера ruki.sys, придумай более жизненный аргумент, плиз.
Re[14]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: infusion  
Дата: 06.08.08 11:53
Оценка: +1 -3 :)
F>Например то, что байт-код перед исполнением компилируется в машинные коды, в отличии от интерпретируемых языков.

здрасть и вы туда же, все не можете смириться что результат вашей работы
суррогат?,
НА ВЫХОДЕ НЕТ ИСПОЛНЯЕМОГО ФАЙЛА,
ТЫ МОЖЕШЬ СКОЛЬКО УГОДНО ГОВОРИТЬ ... ПРО МАШИННЫЕ КОДЫ.

короче вы для меня лично теперь тоже входите в кагорту тех самых
которые так и не уловили смысл сказанного...
... что же там их явка делает на самом то деле ? ась

http://en.wikipedia.org/wiki/Java_(programming_language)
This is achieved by most Java compilers by compiling the Java language code halfway (to Java bytecode) – simplified machine instructions specific to the Java platform. The code is then run on a virtual machine (VM), a program written in native code on the host hardware that interprets and executes generic Java bytecode. (In some JVM versions, bytecode can also be compiled to native code, either before or during program execution, resulting in faster execution.)


Сообщение отредактировано модератором. ДХ
Re[15]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: WFrag США  
Дата: 06.08.08 11:58
Оценка:
Здравствуйте, infusion, Вы писали:

I>здрасть и вы туда же, все не можете смириться что результат вашей работы

I>суррогат?,
I>ДЛЯ ОСОБО "ОДАРЕННЫХ", НА ВЫХОДЕ НЕТ ИСПОЛНЯЕМОГО ФАЙЛА,
I>ТЫ МОЖЕШЬ СКОЛЬКО УГОДНО ГОВОРИТЬ ЧУШЬ ПРО МАШИННЫЕ КОДЫ.

Тебе выхлоп JIT в виде нативного кода показать? Самый настоящий нативный код, который выплёвывает JIT при запуске Java программы.

I>короче вы для меня лично теперь тоже входите в кагорту тех самых

I>которые так и не уловили смысл сказанного, и пытаются дро#ить на
I>тему, что же там их явка делает на самом то деле ? ась

I>http://en.wikipedia.org/wiki/Java_(programming_language)

I>

I>This is achieved by most Java compilers by compiling the Java language code halfway (to Java bytecode) – simplified machine instructions specific to the Java platform. The code is then run on a virtual machine (VM), a program written in native code on the host hardware that interprets and executes generic Java bytecode. (In some JVM versions, bytecode can also be compiled to native code, either before or during program execution, resulting in faster execution.)


Ну. А в скобках парой слов позже прочитать не судьба? Чтоб ты знал, в Sun-овская Java по умолчанию работае в mixed-режиме, когда байткод исполняеться N-раз, а после этого транслируется в нативный код и последующие разы уже выполняется нативный код.
Re[14]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: infusion  
Дата: 06.08.08 11:58
Оценка:
Здравствуйте, fmiracle, Вы писали:
F>Ух ты, какой замечательный ребенок. Еще ничего не знает, но энергия самомнение просто бьют через край.
F>Ознакомься с материалом, узнаешь много чего интересного.

F>Например то, что байт-код перед исполнением компилируется в машинные коды, в отличии от интерпретируемых языков.


надо бы выделить для тебя особенно
(In some JVM versions, bytecode can also be compiled to native code, either before or during program execution, resulting in faster execution.)

но подзреваю ты все равно ничего не понял
Re[15]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Mamut Швеция http://dmitriid.com
Дата: 06.08.08 12:19
Оценка:
I>здрасть и вы туда же, все не можете смириться что результат вашей работы
I>суррогат?,
I>ДЛЯ ОСОБО "ОДАРЕННЫХ", НА ВЫХОДЕ НЕТ ИСПОЛНЯЕМОГО ФАЙЛА,

.so — это исполняемый файл?
список компиляторов, компилирующих Яву в нативный код


dmitriid.comGitHubLinkedIn
Re[16]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: infusion  
Дата: 06.08.08 12:39
Оценка:
Здравствуйте, Mamut, Вы писали:
M>.so — это исполняемый файл?
Представляешь.
это не означает что можно сделать
exec lib.so.

Но начинка в нем вполне себе исполняемая.
Re[15]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.08.08 12:40
Оценка:
Здравствуйте, infusion, Вы писали:


I>здрасть и вы туда же, все не можете смириться что результат вашей работы

I>суррогат?,
I>ДЛЯ ОСОБО "ОДАРЕННЫХ", НА ВЫХОДЕ НЕТ ИСПОЛНЯЕМОГО ФАЙЛА,
I>ТЫ МОЖЕШЬ СКОЛЬКО УГОДНО ГОВОРИТЬ ЧУШЬ ПРО МАШИННЫЕ КОДЫ.

.NET может генерировать .exe файлы, которые вполне исполняемые.
Re[17]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Mamut Швеция http://dmitriid.com
Дата: 06.08.08 12:41
Оценка:
M>>.so — это исполняемый файл?
I>Представляешь.
I>это не означает что можно сделать
I>exec lib.so.

I>Но начинка в нем вполне себе исполняемая.


Это я знаю только, думаю, codelord не об этом говорил. В принципе, с этой целью и был задан вопрос


dmitriid.comGitHubLinkedIn
Re[9]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Vamp Россия  
Дата: 06.08.08 13:10
Оценка:
MyClass::MyClass():
myMember(this)
{}

L>На которые компилятор кричит-кричит, аж надрывается, бедный.

А что тут такого? Совершенно нормальный код. Ты ведь, я надеюсь, в конструкторе myMember методы myClass не дергаешь? А сохранить указатель на обертывающую структуру — вполне нормально для определенного круга задач.
Да здравствует мыло душистое и веревка пушистая.
Re[15]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: fmiracle  
Дата: 06.08.08 13:35
Оценка: +4 -1
Здравствуйте, infusion, Вы писали:

I>здрасть и вы туда же, все не можете смириться что результат вашей работы

I>суррогат?,
I>ДЛЯ ОСОБО "ОДАРЕННЫХ", НА ВЫХОДЕ НЕТ ИСПОЛНЯЕМОГО ФАЙЛА,
I>ТЫ МОЖЕШЬ СКОЛЬКО УГОДНО ГОВОРИТЬ ЧУШЬ ПРО МАШИННЫЕ КОДЫ.

Что-то я не понял — это codelord размножился или в школе клонированных детей сегодня интернет подключили?
Само по себе наличие "исполняемого файла" именно на постоянном носителе может заинтересовать разве что фетишистов.
Обычно интересует работа программы, а не то, как и когда строится исполняемый файл.

Опять же — то что JVM может интерпретировать код, не значит, что она не может его компилировать. Промышленные JVM умеют компилировать код.
Re[13]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: SE Украина  
Дата: 06.08.08 15:45
Оценка:
Здравствуйте, PaulMinelly, Вы писали:

N>>.NET не использует подсчет ссылок. Он строит граф достижимых объектов, остальные автоматически умирают при дефрагментации.


PM>Ну и что это не подсчет ссылок, если ссылок 1 (одна) то объект оставить — если 0, то finalize. Формально, очень даже подсчет ссылок.


На счет простого подсчета ссылок. Если два объекта ссылается друг на друга, то сколько тут ссылок? Правильно, две. А если три объекта ссылаются друг на друга по кругу? Правильно, три.
Но дотнет такие ситуации разруливает очень даже просто. Именно с помошью построения графа достижимых объектов.
Re[11]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 06.08.08 18:13
Оценка:
Здравствуйте, landerhigh, Вы писали:

D>>Неэквивалентно, бо terminate() после исключений из деструкторов, тогда как в C# никаких проблем.


L>Исключения из деструкторов бывают только в случае кривого драйвера ruki.sys,


Про то и речь. А вот Dispose() в C# может их кидать без каких-либо проблем. И поэтому Ваш C++ код не является эквивалентом моего на C#. Ваш код гораздо "глупее".

Если до сих пор не догоняете, то читайте http://www.rsdn.ru/forum/message/3047254.aspx
Автор: drol
Дата: 04.08.08
, http://www.rsdn.ru/forum/message/3047345.aspx
Автор: drol
Дата: 04.08.08
, http://www.rsdn.ru/forum/message/3048703.aspx
Автор: drol
Дата: 05.08.08

и их окрестности.

*Я уже устал n раз одно и то же объяснять...
Re[12]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 06.08.08 18:21
Оценка:
Здравствуйте, drol, Вы писали:

L>>Исключения из деструкторов бывают только в случае кривого драйвера ruki.sys,

D>Про то и речь. А вот Dispose() в C# может их кидать без каких-либо проблем. И поэтому Ваш C++ код не является эквивалентом моего на C#. Ваш код гораздо "глупее".
Ну кинешь ты исключение из финализатора. И что дальше-то? Какой в этом смысл?
Sapienti sat!
Re[13]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: SE Украина  
Дата: 06.08.08 18:36
Оценка:
Здравствуйте, Cyberax, Вы писали:

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


L>>>Исключения из деструкторов бывают только в случае кривого драйвера ruki.sys,

D>>Про то и речь. А вот Dispose() в C# может их кидать без каких-либо проблем. И поэтому Ваш C++ код не является эквивалентом моего на C#. Ваш код гораздо "глупее".
C>Ну кинешь ты исключение из финализатора. И что дальше-то? Какой в этом смысл?

Не подменяйте понятия.
Dispose() и Finalize() очень даже разные методы. В общем случае они даже выполняются в разных потоках: Dispose в том потоке, где собственно ресурсы захватывались, а Finalize в потоке GC.
В кидании исключения из финализатора действительно смысла не много. А вот в кидании исключения из Dispose очень даже смысл есть.
Re[13]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 06.08.08 18:36
Оценка:
Здравствуйте, Cyberax, Вы писали:

L>>>Исключения из деструкторов бывают только в случае кривого драйвера ruki.sys,

D>>Про то и речь. А вот Dispose() в C# может их кидать без каких-либо проблем. И поэтому Ваш C++ код не является эквивалентом моего на C#. Ваш код гораздо "глупее".
C>Ну кинешь ты исключение из финализатора.

Причём здесь finalizer-то ??? Dispose() это обычный метод, и вызывается в обычном контексте исполнения.

C>И что дальше-то? Какой в этом смысл?


См. http://www.rsdn.ru/forum/message/3047423.aspx
Автор: drol
Дата: 05.08.08
Re[14]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 06.08.08 21:03
Оценка:
Здравствуйте, drol, Вы писали:

C>>Ну кинешь ты исключение из финализатора.

D>Причём здесь finalizer-то ??? Dispose() это обычный метод, и вызывается в обычном контексте исполнения.
Ну ладно. Кинешь исключение из Dispose(). Какой в этом смысл?

C>>И что дальше-то? Какой в этом смысл?

D>См. http://www.rsdn.ru/forum/message/3047423.aspx
Автор: drol
Дата: 05.08.08

И? Что мне мешает сделать то же самое из деструктора С++?

Просто единственное ограничение — это не выбрасывать другое исключение за пределы дестркуктора.
Sapienti sat!
Re[15]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: SE Украина  
Дата: 06.08.08 21:34
Оценка:
Здравствуйте, Cyberax, Вы писали:

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


C>>>Ну кинешь ты исключение из финализатора.

D>>Причём здесь finalizer-то ??? Dispose() это обычный метод, и вызывается в обычном контексте исполнения.
C>Ну ладно. Кинешь исключение из Dispose(). Какой в этом смысл?

Да такой же как в выбрасывании любого другого исключения с любом другом месте. Сообщить вызывающему коду об исключительной ситуации.

C>И? Что мне мешает сделать то же самое из деструктора С++?

C>Просто единственное ограничение — это не выбрасывать другое исключение за пределы дестркуктора.

Т.е. внятно сообщить вызывающему коду о невозможности/ощибке освобождения ресурса не получится? Или я неверно понял?
Re[10]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: landerhigh Пират  
Дата: 07.08.08 00:07
Оценка:
Здравствуйте, Vamp, Вы писали:

L>>На которые компилятор кричит-кричит, аж надрывается, бедный.

V>А что тут такого? Совершенно нормальный код. Ты ведь, я надеюсь, в конструкторе myMember методы myClass не дергаешь? А сохранить указатель на обертывающую структуру — вполне нормально для определенного круга задач.
В том-то и дело, что ничего такого нет. Только компилятор норовит ворнинг кинуть. Что усугубляется, когда warnings are threated as errors
Re[11]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Pzz Россия https://github.com/alexpevzner
Дата: 07.08.08 01:07
Оценка:
Здравствуйте, shrecher, Вы писали:

S>В итоге, операции со счетчиком ссылок занимают пару ассемблерных инструкций.


Эта пара инструкций на SMP-системе займет целую вечность из-за необходимости синхронизации кешей процессоров.
Re[7]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Пацак Россия  
Дата: 07.08.08 05:19
Оценка: 1 (1) +1 -1
Здравствуйте, Аноним, Вы писали:

А>c++

А>
А>{
А>  r1.open();
А>  r2.open();
А>  r3.open();
А>  //делаем то, что хотим!!!
А>  ............
А>  //метод close автоматически вызовется в деструкторах
А>}
А>


А>В с++ в случаях удовлетворяющих идиоме RAII можно использовать деструкторы, в более сложных случах обработчики завершения, блоки try catch


Вообще-то, насколько я понимаю, приведенный выше код RAII как раз не соответствует, т.к. вызов open() происходит явно, а не в конструкторе. А значит (сюрпрайз!) если, например, r2.open() вызван не был, а исключение вылетело где-то на этапе r1.open(), то при выходе из блока в деструкторе r2 все равно будет произведена попытка освобождение никогда не занимавшегося им ресурса. Такая вот "красота" и "читабельность".

Но сейчас даже немного не об этом, а вот о чем: уверен ли ты, что в случае, если r1, r2, r3 станут указателями на кучу этот код будет выглядеть так же красиво, как в случае автоматических переменных? В частности ведь в точке "делаем то, что хотим" они могут, например, тупо передаваться ожидающему какого-то события объекту с более широкой областью видимости, которых должен с ними сделать что-то полезное уже сильно опосля того, как завершится данная функция. И как в этом случае будет выглядеть вся эта автоматика с деструкторами?
Ку...
Re[12]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: shrecher  
Дата: 07.08.08 05:33
Оценка: -1
Здравствуйте, Pzz, Вы писали:

S>>В итоге, операции со счетчиком ссылок занимают пару ассемблерных инструкций.


Pzz>Эта пара инструкций на SMP-системе займет целую вечность из-за необходимости синхронизации кешей процессоров.


Лучше ссылок еще не придумали.
Re[15]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.08.08 05:43
Оценка:
Здравствуйте, Cyberax, Вы писали:
D>>Причём здесь finalizer-то ??? Dispose() это обычный метод, и вызывается в обычном контексте исполнения.
C>Ну ладно. Кинешь исключение из Dispose(). Какой в этом смысл?
Очень простой в этом смысл: сообщаем вызывающему, что детерминистическая финализация не удалась.
К примеру, при закрытии файла не удается сделать flush по причине отсутствия доступа к устройству.
В отличие от C++, имеем детерминированный способ обработать эту ситуацию. К примеру, попробовать открыть файл на другом устройстве и повторить операцию записи, которая была прервана исключением.

C>Просто единственное ограничение — это не выбрасывать другое исключение за пределы дестркуктора.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.08.08 06:50
Оценка:
Здравствуйте, Sinclair, Вы писали:

D>>>Причём здесь finalizer-то ??? Dispose() это обычный метод, и вызывается в обычном контексте исполнения.

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

Ну вот допустим, что есть такой код на C#:
using(file1 = new File(...))
using(file2 = new File(...))
using(file3 = new File(...))
  {
    ...bla-bla-bla...
  }

При выходе из блока кода метод Dispose вызывается у file3. И кидает исключение. Что произойдет с объектами file2, file1?

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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[17]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: nikov США http://www.linkedin.com/in/nikov
Дата: 07.08.08 07:29
Оценка: +1
Здравствуйте, eao197, Вы писали:

E>При выходе из блока кода метод Dispose вызывается у file3. И кидает исключение. Что произойдет с объектами file2, file1?


Нетрудно проверить, что у них будут вызваны методы Dispose:

using System;

class File : IDisposable
{
    string name;

    public File(string name)
    {
        this.name = name;
    }

    public void Dispose()
    {
        Console.WriteLine(name + " disposed");
        if (name == null)
            throw new Exception();
    }

    static void Main()
    {
        try
        {
            using (var file1 = new File("file1"))
            using (var file2 = new File("file2"))
            using (var file3 = new File(null))
            {
            
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }
}



 disposed
file2 disposed
file1 disposed
System.Exception: Exception of type 'System.Exception' was thrown.
   at File.Dispose()
   at File.Main()
Re[18]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.08.08 07:36
Оценка: +1
Здравствуйте, nikov, Вы писали:

E>>При выходе из блока кода метод Dispose вызывается у file3. И кидает исключение. Что произойдет с объектами file2, file1?


N>Нетрудно проверить, что у них будут вызваны методы Dispose:


Это не трудно сделать тому, кто пользуется C#-пом

N>
N> disposed
N>file2 disposed
N>file1 disposed
N>System.Exception: Exception of type 'System.Exception' was thrown.
N>   at File.Dispose()
N>   at File.Main()
N>


А что же будет, если выход из блока кода происходит по исключению? Какое исключение будет выпущено наружу -- которое из блока кода или из Dispose?

А так же какое исключение будет выпущенно наружу, если file2 и file3 в своем Dispose будут выбрасывать разные исключения.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: nikov США http://www.linkedin.com/in/nikov
Дата: 07.08.08 07:38
Оценка:
Здравствуйте, eao197, Вы писали:

E>А что же будет, если выход из блока кода происходит по исключению? Какое исключение будет выпущено наружу -- которое из блока кода или из Dispose?


Из Dispose.

E>А так же какое исключение будет выпущенно наружу, если file2 и file3 в своем Dispose будут выбрасывать разные исключения.


То, которое было брошено последним.
Re[20]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 07.08.08 07:40
Оценка:
Здравствуйте, nikov, Вы писали:

N>То, которое было брошено последним.


А чем тогда "последнее" исключение в случае C# лучше, чем "первое" в случае C++?
Или можно получить доступ к текущему исключению и "дописать" туда информацию?
Re[20]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.08.08 07:47
Оценка: +1
Здравствуйте, nikov, Вы писали:

E>>А что же будет, если выход из блока кода происходит по исключению? Какое исключение будет выпущено наружу -- которое из блока кода или из Dispose?


N>Из Dispose.


E>>А так же какое исключение будет выпущенно наружу, если file2 и file3 в своем Dispose будут выбрасывать разные исключения.


N>То, которое было брошено последним.


Ну, собственно, в C# и C++ применены два вполне логичных, но взаимоисключающих подхода к обработке исключений при очистке ресурсов. C++ требует больше работы от разработчика -- задачей разработчика является подавление возможных исключений при очистке ресурсов. C# значительно снижает требования к программисту -- C# сам расставляет за программиста блоки try/catch и сам отвечает за "проглатывания" исключений.

Однако, в любом из подходов потеря исключений происходит.

Вызов terminate в C++ может выглядеть слишком радикальным подходом. Но т.к. в C++ вся ответственность возлагается на программиста, то этот подход вполне в духе C++: не написал try/catch в деструкторе -- получи крах приложения. Что правильно, поскольку выпущенное из деструктора исключение оставляет программу в непонятно каком состоянии. Так что безопаснее рестартовать, чем продолжать работу.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[21]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 08:21
Оценка: +1
Здравствуйте, VoidEx, Вы писали:

VE>А чем тогда "последнее" исключение в случае C# лучше,


В C# нет никакого "последнего". Если Вам требуются остальные исключения, то Вы просто обкладываете нужные фрагменты соответствующими try/catch, и можете получить хоть всю цепочку.

VE>чем "первое" в случае C++?


В С++ нет никакого "первого". Из деструкторов C++ не бросают исключений.
Re[22]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: nikov США http://www.linkedin.com/in/nikov
Дата: 07.08.08 08:24
Оценка:
Здравствуйте, drol, Вы писали:

D>В C# нет никакого "последнего". Если Вам требуются остальные исключения, то Вы просто обкладываете нужные фрагменты соответствующими try/catch, и можете получить хоть всю цепочку.


Разве с помощью try-catch в деструкторах C++ я не могу получить то же самое?
Re[22]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 07.08.08 08:25
Оценка:
Здравствуйте, drol, Вы писали:

D>В C# нет никакого "последнего". Если Вам требуются остальные исключения, то Вы просто обкладываете нужные фрагменты соответствующими try/catch, и можете получить хоть всю цепочку.

Покажите, пожалуйста, на этом примере:

using (var file1 = new File( ... ))
using (var file2 = new File( ... ))
{
  // ...
}
Re[22]: Exception в Finally
От: SE Украина  
Дата: 07.08.08 09:40
Оценка: 3 (1) -1
Здравствуйте, drol, Вы писали:

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


VE>>А чем тогда "последнее" исключение в случае C# лучше,


D>В C# нет никакого "последнего". Если Вам требуются остальные исключения, то Вы просто обкладываете нужные фрагменты соответствующими try/catch, и можете получить хоть всю цепочку.


На самом деле есть "последний". Не получите вы цепочку, и не надейтесь. Вот вам пример
using System;

namespace Finally
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                try
                {
                    throw new Exception("1");
                }
                catch (Exception ex)
                {
                    throw new Exception("2", ex);
                }
                finally
                {
                    // именно в блоке finally зызывается метод Dispose
                    throw new Exception("3");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
    }
}


Результат:
System.Exception: 3
   at Finally.Program.Main(String[] args) in D:\Projects\Tests\Finally\Program.cs:line 22


Итого имеем потерянную информацию об "1" и "2". Если закомментировать строку throw new Exception("3"); то потери стека не будет и выведется инфа про "1" и "2". Но нас то интересует случай с исключением!
Re[16]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 10:02
Оценка: 4 (1) +1
Здравствуйте, SE, Вы писали:

C>>Ну ладно. Кинешь исключение из Dispose(). Какой в этом смысл?

SE>Да такой же как в выбрасывании любого другого исключения с любом другом месте. Сообщить вызывающему коду об исключительной ситуации.
Ага, и затереть собой предидущее исключение.

C>>Просто единственное ограничение — это не выбрасывать другое исключение за пределы дестркуктора.

SE>Т.е. внятно сообщить вызывающему коду о невозможности/ощибке освобождения ресурса не получится? Или я неверно понял?
Неверно. Повторный выброс исключения в C#/Java затирает предидущее исключение. И вместо осмысленного UserPluggedOffUSBDriveException мы получим невнятный IOException при закрытии файла.
Sapienti sat!
Re[16]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 10:04
Оценка:
Здравствуйте, Sinclair, Вы писали:

C>>Ну ладно. Кинешь исключение из Dispose(). Какой в этом смысл?

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

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

Кто мне мешает сделать то же самое в C++?
Sapienti sat!
Re[23]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 11:20
Оценка:
Здравствуйте, nikov, Вы писали:

D>>В C# нет никакого "последнего". Если Вам требуются остальные исключения, то Вы просто обкладываете нужные фрагменты соответствующими try/catch, и можете получить хоть всю цепочку.


N>Разве с помощью try-catch в деструкторах C++ я не могу получить то же самое?


Неа.

В С++ (по-факту, стандарт вполне разрешает) нельзя бросать исключения из деструкторов. Связано это с тем, что если исключение бросится из деструктора в процессе раскрутки стека, то (согласно стандарту) последует вызов terminate() и завершение работы программы. Так что внутри деструктора наловить можно много, но вот наружу ничего не вытащить.

Rationale этого решения стандарта, лично я, внятно изложить не могу, хотя идеи есть Вообще было бы интересно почитать чего-нибудь advanced на тему...

*Кстати, попробуйте мыслить деструктор C++ как финалайзер .NET, уважаемый nikov. Я уже показывал в этом топике, что их свойства идентичны. И спецификация C# совершенно неспроста финалайзеры именует деструкторами
Re[24]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 07.08.08 11:29
Оценка:
Здравствуйте, drol, Вы писали:

D>В С++ (по-факту, стандарт вполне разрешает) нельзя бросать исключения из деструкторов. Связано это с тем, что если исключение бросится из деструктора в процессе раскрутки стека, то (согласно стандарту) последует вызов terminate() и завершение работы программы. Так что внутри деструктора наловить можно много, но вот наружу ничего не вытащить.


D>Rationale этого решения стандарта, лично я, внятно изложить не могу

Например как добивать локальный объект, который при выходе из функции в своем деструкторе вдруг кинул исключение? По идее это означает что деструкция не была полностью завершена, объект не был корректно удален, но, тем не менее выход из функции уже его недобитые останки закопал. Что делать? Как его добить в такой ситуации?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[23]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.08.08 11:32
Оценка:
Здравствуйте, VoidEx, Вы писали:

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


D>>В C# нет никакого "последнего". Если Вам требуются остальные исключения, то Вы просто обкладываете нужные фрагменты соответствующими try/catch, и можете получить хоть всю цепочку.

VE>Покажите, пожалуйста, на этом примере:

VE>
VE>using (var file1 = new File( ... ))
VE>using (var file2 = new File( ... ))
VE>{
VE>  // ...
VE>}
VE>

Ну копец какой, рокет сайенс. Очевидно, что исключение здесь может вылететь в трех местах:
а) в file1.Dispose
б) в file2.Dispose
в) в // ...

Вот как мы ловим всё, что нам нужно:

try
{
  using (var file1 = new File( ... ))
  try
  {
    using (var file2 = new File( ... ))
    {
      try
      {
        // ...
      }
      catch(Exception e3)
      { ... }
    }
  } 
  catch (Exception e2)
  {  }
}
catch (Exception e1)
{  }

Какие проблемы?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[24]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 07.08.08 11:38
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

S>Какие проблемы?


Вот и я хочу узнать, какие?

try
{
  File file1( ... );
  try
  {
    File file2( ... );
    try
    {
      // ...
    }
    catch ( ... ) {}
  }
  catch ( ... ) {}
}
catch ( ... ) {}
Re[17]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 11:40
Оценка: :)
Здравствуйте, Cyberax, Вы писали:

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

C>Кто мне мешает сделать то же самое в C++?

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

А больше ничего не мешает. Передвигаете логику очистки ресурса из деструктора в обычную функцию-член, пишите код аналогичный try/finally/using/IDisposable на try/catch'ах и всё. Да, выглядеть будет страшненько, так как try/finally в C++ отсутствует (невозможен?)

*И напоследок. Вы топик вообще читали, уважаемый ??? Я уже раза три разжёвывал тему. Мне обязательно это делать для каждого очередного "чукчи-писателя" зашедшего на огонёк ???
Re[17]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.08.08 11:41
Оценка:
Здравствуйте, Cyberax, Вы писали:
S>>Очень простой в этом смысл: сообщаем вызывающему, что детерминистическая финализация не удалась.
C>И что он с этим будет делать?
Читать постинги целиком.

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

C>Кто мне мешает сделать то же самое в C++?
То, что после terminate ничего сделать уже нельзя.
Еще раз поясняю: обычно никакого интереса к повторным исключениям у вызывающего нет. Вот, допустим, код устроен примерно таким образом:

public bool ProcessJob(job j)
{
  try
  {
    using(Stream s = GetStreamForJob(j))
      WriteData(s);
    return true;
  }
  catch (Exception e)
  {
    return false;
  }
}

public bool ProcessJobStep(JobQueue q)
{
  Job j = q.Dequeue();
  j.Attempts++;
  if (!ProcessJob(j))
    q.Enqueue(); // return to queue for another attempt
}

Совершенно нармальная ситуация. Нам не нужно беспокоиться, что деструктор стрима не сможет сделать flush. Значит, мы можем перейти от небуферизованного стрима к буферизованному. Нам вообще все равно, где возникло исключение: главное, что мы отличаем ситуацию успешной записи от неудачи. В C++ придется делать flush руками, потому что попытка сделать flush в деструкторе приведет к проглоту исключения.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[25]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 11:43
Оценка: +1
Здравствуйте, VoidEx, Вы писали:

S>>Какие проблемы?


VE>Вот и я хочу узнать, какие?


VE>
VE>try
VE>{
VE>  File file1( ... );
VE>  try
VE>  {
VE>    File file2( ... );
VE>    try
VE>    {
VE>      // ...
VE>    }
VE>    catch ( ... ) {}
VE>  }
VE>  catch ( ... ) {}
VE>}
VE>catch ( ... ) {}
VE>


Те же самые. Деструкторы не могут бросать исключения. Посему об ошибках I/O при закрытии файла вызывающий код никогда не узнает.
Re[26]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.08.08 11:48
Оценка:
Здравствуйте, drol, Вы писали:

D>Те же самые. Деструкторы не могут бросать исключения. Посему об ошибках I/O при закрытии файла вызывающий код никогда не узнает.


А теперь вопрос: что важнее -- знать про первое исключение, которое спровоцировало раскрутку стека (подход C++), или последнее исключение, которое было порождено в результате раскрутки стека (подхож C#)?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[18]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.08.08 11:52
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

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


Если нам все равно и главное знать про успех/неудачу, то какая разница, что в C++ flush-ширование в деструкторе будет проходить с проглатыванием исключения?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 07.08.08 12:05
Оценка:
Здравствуйте, eao197, Вы писали:

E>Если нам все равно и главное знать про успех/неудачу, то какая разница, что в C++ flush-ширование в деструкторе будет проходить с проглатыванием исключения?


Ну так в Си++ деструктор не выкинет ничего, и будет вроде всё хорошо.
А там исключение вылетит, просто возможно оно затрёт предыдущее.
Re[27]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.08.08 12:11
Оценка: -1
Здравствуйте, eao197, Вы писали:

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


D>>Те же самые. Деструкторы не могут бросать исключения. Посему об ошибках I/O при закрытии файла вызывающий код никогда не узнает.


E>А теперь вопрос: что важнее -- знать про первое исключение, которое спровоцировало раскрутку стека (подход C++), или последнее исключение, которое было порождено в результате раскрутки стека (подхож C#)?


Откройте для себя InnerException
Re[28]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 07.08.08 12:12
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>Откройте для себя InnerException


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

C>>Кто мне мешает сделать то же самое в C++?

S>То, что после terminate ничего сделать уже нельзя.
А зачем мне делать terminate?

S>Еще раз поясняю: обычно никакого интереса к повторным исключениям у вызывающего нет. Вот, допустим, код устроен примерно таким образом:

S>
S>public bool ProcessJob(job j)
S>{
S>  try
S>  {
S>    using(Stream s = GetStreamForJob(j))
S>      WriteData(s);
S>    return true;
S>  }
S>  catch (Exception e)
S>  {
S>    return false;
S>  }
S>}
S>public bool ProcessJobStep(JobQueue q)
S>{
S>  Job j = q.Dequeue();
S>  j.Attempts++;
S>  if (!ProcessJob(j))
S>    q.Enqueue(); // return to queue for another attempt
S>}
S>


bool process_job(job j)
{
  try
  {
     stream s(get_stream_for_job(j));
     write_data(s);
     return true;
  } catch(...) {return false;}
}

И в деструкторе stream просто не бросаем повторное исключение.

S>Совершенно нармальная ситуация. Нам не нужно беспокоиться, что деструктор стрима не сможет сделать flush. Значит, мы можем перейти от небуферизованного стрима к буферизованному. Нам вообще все равно, где возникло исключение: главное, что мы отличаем ситуацию успешной записи от неудачи. В C++ придется делать flush руками, потому что попытка сделать flush в деструкторе приведет к проглоту исключения.

Мы можем выпускать исключение, если в данный момент не активно другое. Как вариант — можно сделать подход с флагами:

bool process_job(job j)
{
     stream *str=get_stream_for_job(j);

     stream_handle hndl(str);
     write_data(hndl);

     return str->is_error_flag_set();
}


Конкретно второй вариант мне нравится больше.
Sapienti sat!
Re[18]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 12:24
Оценка: 1 (1) +1
Здравствуйте, drol, Вы писали:

C>>Кто мне мешает сделать то же самое в C++?

D>Как вызывающий деструкторы код узнает о том, что ж случилось и нужно реагировать, если деструкторы не могут бросать исключения ??? Ну что непонятного-то ???
Разными путями — установкой флагов, например. Что, у нас нет ничего кроме исключений?

Вообще, дизайн с броском исключений в деструкторах — кривой по своей сути.

D>*И напоследок. Вы топик вообще читали, уважаемый ??? Я уже раза три разжёвывал тему. Мне обязательно это делать для каждого очередного "чукчи-писателя" зашедшего на огонёк ???

Читал, читал. Я про работу исключений вообще знаю в глубоких ассемблерных подробностях.
Sapienti sat!
Re[25]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 12:49
Оценка:
Здравствуйте, CreatorCray, Вы писали:

D>>Rationale этого решения стандарта, лично я, внятно изложить не могу

CC>Например как добивать локальный объект, который при выходе из функции в своем деструкторе вдруг кинул исключение? По идее это означает что деструкция не была полностью завершена, объект не был корректно удален, но, тем не менее выход из функции уже его недобитые останки закопал. Что делать? Как его добить в такой ситуации?

Не годится. Один-то уровень исключений из деструктора я ведь могу организовать. А там всё точно так же: недобитый объект, все дела... Однако не мешает

Я всё-таки полагаю, что смотреть надо в сторону стека и расположения объектов на нём. В особенности собственно исключения и локальных объектов создаваемых/уничтожаемых вызываемыми при раскрутке деструкторами.
Re[23]: Exception в Finally
От: SE Украина  
Дата: 07.08.08 12:56
Оценка:
Здравствуйте, SE, Вы писали:

SE>На самом деле есть "последний". Не получите вы цепочку, и не надейтесь.


Может быть уважаемый Sinclair вместо раздачи минусов направо и налево объяснит, с чем он в примере не согласен, и каким образом можно восстановить цепочку исключений случившихся в using после исключения в методе Dispose?
Я с благодарностью выслушаю, как это можно сделать. А пример кода был бы просто бальзамом на душу.
Re[20]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.08.08 13:07
Оценка:
Здравствуйте, VoidEx, Вы писали:

E>>Если нам все равно и главное знать про успех/неудачу, то какая разница, что в C++ flush-ширование в деструкторе будет проходить с проглатыванием исключения?


VE>Ну так в Си++ деструктор не выкинет ничего, и будет вроде всё хорошо.

VE>А там исключение вылетит, просто возможно оно затрёт предыдущее.

Упс... Ступил


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 13:09
Оценка: 1 (1) +2 -1
Здравствуйте, Cyberax, Вы писали:

C>>>Кто мне мешает сделать то же самое в C++?

D>>Как вызывающий деструкторы код узнает о том, что ж случилось и нужно реагировать, если деструкторы не могут бросать исключения ??? Ну что непонятного-то ???
C>Разными путями — установкой флагов, например. Что, у нас нет ничего кроме исключений?

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

C>Вообще, дизайн с броском исключений в деструкторах — кривой по своей сути.


Разумеется! Я совершенно с Вами согласен. И именно поэтому в нормальных языках типа C# сделаны try/finally/using/IDisposable и GC впридачу. Бо не надо мешать задачу управления циклом жизни объекта в одну кучу с задачей управления памятью, занимаемой этим самым объектом.
Деструктор/finalizer не должен бросать исключения, их должен бросать совершенно обычный метод, предназначенный для закрытия ресурса и используемый в нормальном контексте исполнения программы. В случае C# это IDisposable.Dispose()

C>Я про работу исключений вообще знаю в глубоких ассемблерных подробностях.


Тогда Вы, наверняка, сумеете ответить на мой вопрос о rationale положений стандарта о вызове terminate(), в случае исключения при развёртке стека. Или не сможете ?
Re[26]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 07.08.08 13:14
Оценка:
Здравствуйте, drol, Вы писали:

D>Не годится. Один-то уровень исключений из деструктора я ведь могу организовать. А там всё точно так же: недобитый объект, все дела... Однако не мешает

D>Я всё-таки полагаю, что смотреть надо в сторону стека и расположения объектов на нём. В особенности собственно исключения и локальных объектов создаваемых/уничтожаемых вызываемыми при раскрутке деструкторами.
Ты вопрос то понял?
Вопрос в том, что вот покинул объект область видимости и сработал его деструктор. А в деструкторе на полдороги вылетело исключение и некоторые нужные шаги в деструкторе не выполнились. Ты это исключение где то выше поймал и как то обработал. Как теперь "додеструктить" объект то?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[20]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 07.08.08 13:14
Оценка: :)
Здравствуйте, drol, Вы писали:

C>>Разными путями — установкой флагов, например. Что, у нас нет ничего кроме исключений?

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

D>Разумеется! Я совершенно с Вами согласен. И именно поэтому в нормальных языках типа C# сделаны try/finally/using/IDisposable и GC впридачу. Бо не надо мешать задачу управления циклом жизни объекта в одну кучу с задачей управления памятью, занимаемой этим самым объектом.

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

C>>Я про работу исключений вообще знаю в глубоких ассемблерных подробностях.

D>Тогда Вы, наверняка, сумеете ответить на мой вопрос о rationale положений стандарта о вызове terminate(), в случае исключения при развёртке стека. Или не сможете ?
Смогу. Оно нужно для гарантии того, что изначальное исключение не будет молчаливо затёрто.
Sapienti sat!
Re[20]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.08.08 13:39
Оценка:
Здравствуйте, drol, Вы писали:

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


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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[27]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 13:44
Оценка: +1
Здравствуйте, CreatorCray, Вы писали:

D>>Не годится. Один-то уровень исключений из деструктора я ведь могу организовать. А там всё точно так же: недобитый объект, все дела... Однако не мешает

D>>Я всё-таки полагаю, что смотреть надо в сторону стека и расположения объектов на нём. В особенности собственно исключения и локальных объектов создаваемых/уничтожаемых вызываемыми при раскрутке деструкторами.
CC>Вопрос в том, что вот покинул объект область видимости и сработал его деструктор. А в деструкторе на полдороги вылетело исключение и некоторые нужные шаги в деструкторе не выполнились. Ты это исключение где то выше поймал и как то обработал. Как теперь "додеструктить" объект то?

Ниже в точности Ваш пример. Всё замечательно ловится и успешно доходит до "return 0;" безо всяких terminate()
И при этом объект a не менее успешно "недодеструкчен"...

#include <exception>
#include <iostream>

using namespace std;

class A {
public:
    ~A() {
        cout<<"~A() (before throw)"<<endl;
        throw exception();
        cout<<"~A() (after throw)"<<endl;
    }
};

int main(int, char**) {
    try {
        A a;
    } catch(...) {
        cout<<"exception catched"<<endl;
    }

    cout<<"OK => return 0"<<endl;

    return 0;
}


*Читайте стандарт, он рулез
Re[28]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 07.08.08 14:01
Оценка:
Здравствуйте, drol, Вы писали:

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


D>>>Не годится. Один-то уровень исключений из деструктора я ведь могу организовать. А там всё точно так же: недобитый объект, все дела... Однако не мешает

D>>>Я всё-таки полагаю, что смотреть надо в сторону стека и расположения объектов на нём. В особенности собственно исключения и локальных объектов создаваемых/уничтожаемых вызываемыми при раскрутке деструкторами.
CC>>Вопрос в том, что вот покинул объект область видимости и сработал его деструктор. А в деструкторе на полдороги вылетело исключение и некоторые нужные шаги в деструкторе не выполнились. Ты это исключение где то выше поймал и как то обработал. Как теперь "додеструктить" объект то?

D>Ниже в точности Ваш пример. Всё замечательно ловится и успешно доходит до "return 0;" безо всяких terminate()

D>И при этом объект a не менее успешно "недодеструкчен"...

Третий раз повторяю: И как его корректно додеструктить после этого? Объект покинул зону видимости и не доступен. Получается что исключение выброшенное из деструктора не может гарантировать правильную раскрутку стека.

+ попробуй вот этот вариант:
#include <exception>
#include <iostream>

using namespace std;

class A {
public:
    A(int v)    {m_v = v; cout << "A(" << v << ");\n";}
    ~A() {
        cout<<"~A(" << m_v <<") (before throw)"<<endl;
        throw exception();
        cout<<"~A(" << m_v <<") (after throw)"<<endl;
    }

    int m_v;
};

int main(int, char**) {
    try {
        A a(1),b(2);
    } catch(...) {
        cout<<"exception catched"<<endl;
    }

    cout<<"OK => return 0"<<endl;

    return 0;
}


у меня он приводит к крэшу приложения при повторном исключении.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[29]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 07.08.08 14:14
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Третий раз повторяю: И как его корректно додеструктить после этого? Объект покинул зону видимости и не доступен.


Никак. Однако, как Вы могли убедиться на моём примере, с точки зрения C++, программе это не мешает.

CC>Получается что исключение выброшенное из деструктора не может гарантировать правильную раскрутку стека.


"Правильная раскрутка" это то что допускает стандарт. Мой пример он допускает, и значит проблема не в "недодеструкченности".

CC>+ попробуй вот этот вариант:

CC>у меня он приводит к крэшу приложения при повторном исключении.

Конечно приводит, бо у Вас там два объекта. При выходе из блока вызывается деструктор для b. В нём происходит исключение. Стартует раскрутка стека. Она вызывает деструктор a. И в нём тоже происходит исключение. Только на сей раз это исключение при раскрутке стека, и строго согласно стандарту следует terminate()

Если в Вашем примере оставить только один объект — всё будет нормально. То бишь "недодеструкченный" объект + продолжающая работать как ни в чём не бывало программа.
Re[17]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: IB Австрия http://rsdn.ru
Дата: 07.08.08 15:35
Оценка:
Здравствуйте, Cyberax, Вы писали:

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

Не всегда. Справедливости ради, надо заметить, что есть и InnerException и просто throw без параметров, что в том или ином виде делает доступным оригинальное исключение выше по стеку.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[18]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: nikov США http://www.linkedin.com/in/nikov
Дата: 07.08.08 16:18
Оценка: +1
Здравствуйте, IB, Вы писали:

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

IB>Не всегда. Справедливости ради, надо заметить, что есть и InnerException и просто throw без параметров, что в том или ином виде делает доступным оригинальное исключение выше по стеку.

Покажи код, если можно.
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++.
Re[28]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 08.08.08 07:56
Оценка: -1
Здравствуйте, VoidEx, Вы писали:

VE>Кстати, за это надо руки отрывать, или нет?


Полагаю что надо

VE>Просто основной упор делается на то, что, мол, в деструкторах кинуть исключение нельзя.


Нет, основной упор делается на то, что из деструкторов нельзя бросать исключения во время раскрутки стека.

VE>Тогда какие отличия? Только в том, что в шарпе долетает последнее исключение из всей цепочки, а в Си++ — первое.


Неверно. Отличия в том, что в C++ у Вас при раскрутке стека вообще ни одного исключения, а в C# Вы можете без проблем получить любые, что пробрасываются через метод.

VE>Но во-первых в ветке else можно куда-то что-то записать,


Ага-ага. "Глобальные флаги наносят ответный удар 2"...

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


А я вот выберу только те исключения, которые меня интересуют.

VE>Но это отдельная тема для дискуссий. В идеале хорошо было бы получить все исключения.


C# предоставляет Вам такую возможность. С++ — нет.

VE>И не пойму, что мешало в шарпе сделать так, чтобы при броске нового исключения предыдущее не затиралось,


Ничего не затирается. То что оппоненты почему-то упорно называют "затиранием", является обычной обработкой исключения по-типу try/catch.

VE>а записывалось новому в Inner автоматически?


Видимо потому что у нового уже может быть свой InnerException. "Новое"-то ведь на самом деле тоже может являться n-ым в своей личной цепи исключений...
Re[29]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 08.08.08 08:47
Оценка: 11 (1) +1
Здравствуйте, drol, Вы писали:

D>Нет, основной упор делается на то, что из деструкторов нельзя бросать исключения во время раскрутки стека.


D>Неверно. Отличия в том, что в C++ у Вас при раскрутке стека вообще ни одного исключения, а в C# Вы можете без проблем получить любые, что пробрасываются через метод.


Вы определитесь.
То только во время раскрутки нельзя кидать, то вообще ни одного...
Я же привёл пример, можно 10 объектов создать, с базовыми, с мемберами. И у всех вызовутся деструкторы, все закроется, а исключения или вылетят, или допишутся в текущее.

D>Ага-ага. "Глобальные флаги наносят ответный удар 2"...


Конечно, способ хранить "текущее" исключение не хорош, ну так исключение может быть любого типа, так что хотя бы.

D>А я вот выберу только те исключения, которые меня интересуют.


И как же? Либо так же оборачивать каждый using в try-catch — или извольте, только последнее.

VE>>Но это отдельная тема для дискуссий. В идеале хорошо было бы получить все исключения.


D>C# предоставляет Вам такую возможность. С++ — нет.


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

D>Ничего не затирается. То что оппоненты почему-то упорно называют "затиранием", является обычной обработкой исключения по-типу try/catch.


То ли вы поняли, что ошиблись, и теперь виляете туда-сюда, то ли и правда не понимаете.
Вам привели пример, когда долетает только последнее исключение, где предыдущее?
Ответ — "обернуть своим try-catch" аналогичен аругменту за возвращаемые значения — "так надо же возвращаемое значение проверять!". Тогда чем исключение лучше-то?
Исключение тем и хорошо, что всегда попадает в catch на каком-либо уровне и избежать этого нельзя (по идее так должно быть), но вот пример, что делать если исключения сразу два. В шарпе — игнор, в Си++ — terminate. Ни одно решение не универсально.
От того, что вы всё в try-catch обернёте, факт этот никуда не денется.
Получается ещё хуже — не кидать исключения ни в диспозах, ни в финалли, а то вдруг предыдущее затрётся. Как вы тогда получите "то исключение, которое вас интересует"?

Кстати, есть ли аналог std::uncaught_exception?
Re[26]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 08.08.08 08:51
Оценка:
Здравствуйте, drol, Вы писали:

D>Я не знаю как объяснить проще и доступнее. Если Вы не понимаете такой элементарщины, то я Вам ничем помочь больше не могу...

Аналогично. Я считаю, что система должна быть надёжной. И в случае нештатной ситуации корректно завершатся, а не пытаться имитировать, что всё нормально.

C>>Нет. В Java/.NET мы без следов теряем изначальное исключение.

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

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

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

C>>Неправда. Мы в блоке finally кидаем исключение, которое ЗАМЕНЯЕТ выброщенный RuntimeException.

D>Чушь. Никто ничего не заменяет. try/finally это по-факту синтаксический сахар на базе try/catch/throw, то есть обычной обработки исключения с его возможным "пробросом". Если Вы обложите try/catch'ем содержимое finally-блока, то на выходе получите свой любимый RuntimeException. А вот теперь попробуйте сделать то же самое с вызовом деструктора автоматического объекта в C++...
Покажи код.

C>>В C++ в этом случае для надёжности решили делать std::terminate.

D>Ну всё, приехали, terminate==надёжность... Даже не знаю что и сказать-то. Разве что порекомендовать почитать БСЭ на тему... раз эдак семь.
Да, это надёжность. Рекомендую прочитать про http://en.wikipedia.org/wiki/Fail-safe . Решение с std::terminate как раз является таковым.

C>>Существует. Выполнение блоков finally — ну абсолютно то же самое. Оно даже внутри реализовано так же.

D>См. выше. try/finally в этом моменте реализован через try/catch. Никакой раскрутки здесь нет.
Да? Ну совсем нет?
void function1()
{
   try
   {
       throw new IllegalStateException();
   } finally
   {
       System.out.println("1");
   }
}

void function2()
{
   try
   {
       function1();
   } finally
   {
       System.out.println("2");
   }
   System.out.println("3");
}


void function3()
{
   try
   {
       function2();
   } finally
   {
       System.out.println("4");
   }
   System.out.println("5");
}


Что будет напечатано при вызове function3() ?
Sapienti sat!
Re: Зачем нужен сборщик мусора? Как жить без деструкторов?
От: Adriano  
Дата: 08.08.08 09:50
Оценка: 1 (1)
Наверно вы все не раз встречали подобный код:

java
myLock.lock();
try {
  //критический фрагмент кода
  ...............
}
finally{
  myLock.unlock();
}

или
Connection conn = getConnection();
try {
  //че-то делаем
  ....
}
finally {
  conn.close();
}


Примеры взял из книжки по яве, которая лежит у меня на столе (Кей. С. Хорстман, Библиотека профессионала. Java 2). Посмотрим теперь плагины из Eclipse — увидим примерно тоже самое: файлы и соединения закрываются без проверки результата. Найдем участки кода из Windows или Linux — то же самое, мьютексы освобождается без проверки! Оказывается существуют случаи, и это абсолютное большинство случаев, когда не нужно проверять результат уничтожения ресурса. И хочу заметить, что Windows, Linux, Eclipse – это очень серьезные проекты, которые созданы далеко не дилетантами. И почему-то мне кажется, что даже drol, котоырй так активно утверждает, что надо проверять все и везде, на самом деле закрывает файл “немой” строкой file.close();

Для этого в с++ существуют деструкторы. Конкретный пример, где в деструкторе выполняется уничтожение обьекта — std::ifstream:
{
  std::ifstream file("data.txt");
  if ( !file ) {
    return false;//файл не открылся
  }
  //работаем с файлом
  .....
  //файл закроется автоматически, при уничтожении обьекта
}

Как видим все очень просто и никакого оверхеда!


Бывают случаи, когда необходимо контролировать уничтожение ресурса и реагировать на различные ошибки. Это встречается гораздо реже, но встречается. В этом случае деструктор — не лучший вариант. Но мы делаем так:

c++
r.open();
try {
  //критический код
  ...
}
catch(...){//либо перехватываем все исключения, либо базовое(std::exception), как надо так и делаем
  //поймано исключение
  ...
}
r.close();//кидаем исключения на право и на лево так, что б аж в глазах потемнело

Все просто и понятно.
Re[23]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: IB Австрия http://rsdn.ru
Дата: 08.08.08 10:33
Оценка:
Здравствуйте, Cyberax, Вы писали:

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

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

C>Не совсем согласен, что оно существенное.

Нормальный ход — ты утверждаешь, что исключение при перехвате проглатывается, но замечание о том, что, на самом деле, оригинальное исключение в том или ином виде может быть доступно выше по стеку ты находишь не существенным...
Ну, типа, "это противоречит том что я говорил, поэтому это не существенно". =)
... << RSDN@Home 1.2.0 alpha rev. 673>>
Мы уже победили, просто это еще не так заметно...
Re[8]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Adriano  
Дата: 08.08.08 10:53
Оценка:
Здравствуйте, Пацак, Вы писали:

П>Здравствуйте, Аноним, Вы писали:


А>>c++

А>>
А>>{
А>>  r1.open();
А>>  r2.open();
А>>  r3.open();
А>>  //делаем то, что хотим!!!
А>>  ............
А>>  //метод close автоматически вызовется в деструкторах
А>>}
А>>


А>>В с++ в случаях удовлетворяющих идиоме RAII можно использовать деструкторы, в более сложных случах обработчики завершения, блоки try catch


П>Вообще-то, насколько я понимаю, приведенный выше код RAII как раз не соответствует, т.к. вызов open() происходит явно, а не в конструкторе. А значит (сюрпрайз!) если, например, r2.open() вызван не был, а исключение вылетело где-то на этапе r1.open(), то при выходе из блока в деструкторе r2 все равно будет произведена попытка освобождение никогда не занимавшегося им ресурса. Такая вот "красота" и "читабельность".


Конкретный пример — std::fstream.
Можно так:
{
std::fstream f("1.txt");
...
}

или так:
{
std::fstream f;
f.open("1.txt");
...
}

оба варианта верные
Re[30]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 08.08.08 12:22
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Вы определитесь.

VE>То только во время раскрутки нельзя кидать, то вообще ни одного...

Я уже n раз всё подробно разжёвывал. Могу ещё раз, почти привык уже...

Если нельзя бросать исключения из деструкторов во время раскрутки стека, то по-факту это приводит практически к полному запрету на исключения из деструкторов.
Основания очевидные. Если какой-то деструктор всё-таки бросает исключения, то любая раскрутка стека с автоматическим объектом этого типа и сразу terminate() Остаётся вариант с проверкой uncaught_exception(), однако при нём мы получаем неконсистентное поведение — исключение может быть, а может и не быть...

Посему оппоненты, например, неоднократно постулировали запрет на исключения в деструкторе. И в этом вопросе я с ними согласен, заметьте

VE>Я же привёл пример, можно 10 объектов создать, с базовыми, с мемберами. И у всех вызовутся деструкторы, все закроется, а исключения или вылетят, или допишутся в текущее.


Ваш пример есть полный ужОс.

1. Привязан к кастомному типу, через него нельзя даже просто std::exception() "бросить".
2. Так как во время раскрутки в реальности ничего не бросается, то для Ваших псевдоисключений в деструкторах не работает try/catch. Вам его придётся как-то имитировать ручками, при этом обычный try/catch тоже должен нормально работать.
3. ...

Можно и дальше продолжать, но предлагаю попробовать хотя бы первые два пункта доточить. С интересом погляжу

VE>И как же? Либо так же оборачивать каждый using в try-catch


Да, именно так. Чтобы что-то сделать, надо написать код. Если Вы можете придумать как обрабатывать конкретное исключение без кода, с большим интересом послушаю.

VE>Ни тот, ни другой не предоставляет. В шарпе вы ловите лишь последнее исключение.

VE>Оборачивать каждый пук в try-catch можно везде,

Чушь. В C++ вызов деструктора автоматического объекта обернуть в try-catch невозможно. Если Вы это отрицаете — показывайте пример.

VE>Вам привели пример, когда долетает только последнее исключение, где предыдущее?


Оно было поймано и обработано. Это try/catch, а не "затирание".

VE>Ответ — "обернуть своим try-catch" аналогичен аругменту за возвращаемые значения — "так надо же возвращаемое значение проверять!". Тогда чем исключение лучше-то?


Тем что пробрасывается сквозь стек вызовов, до тех пор пока кто знает что делать не поймает.

VE>Получается ещё хуже — не кидать исключения ни в диспозах, ни в финалли, а то вдруг предыдущее затрётся.


Чушь. Все кидают, только шум стоит. И никаких проблем. Потому что ничего не "затирается", а ловится и обрабатывается.

VE>Кстати, есть ли аналог std::uncaught_exception?


В C# нет раскрутки стека, и код, за исключением finalizer'ов, исполняется в обычном контексте. Мне вот непонятно где можно использовать, даже если и есть... Разве что на уровне MSIL уже...
Re[31]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 08.08.08 12:49
Оценка:
Здравствуйте, drol, Вы писали:

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


D>Основания очевидные. Если какой-то деструктор всё-таки бросает исключения, то любая раскрутка стека с автоматическим объектом этого типа и сразу terminate() Остаётся вариант с проверкой uncaught_exception(), однако при нём мы получаем неконсистентное поведение — исключение может быть, а может и не быть...

В C# мы получаем поведение — исключение вылетит, но может затереть то, которое уже летит.
В C++ долетает только то, что вылетело первым, последующие — не бросаются.
Совпадение и разница видны?

VE>>И как же? Либо так же оборачивать каждый using в try-catch


D>Да, именно так. Чтобы что-то сделать, надо написать код. Если Вы можете придумать как обрабатывать конкретное исключение без кода, с большим интересом послушаю.


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

D>Чушь. В C++ вызов деструктора автоматического объекта обернуть в try-catch невозможно. Если Вы это отрицаете — показывайте пример.


Раз
Автор: Sinclair
Дата: 07.08.08

Два
Автор: VoidEx
Дата: 07.08.08

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

VE>>Вам привели пример, когда долетает только последнее исключение, где предыдущее?


D>Оно было поймано и обработано. Это try/catch, а не "затирание".


facepalm
Здесь
Автор: Cyberax
Дата: 08.08.08
приведён код.
Куда улетело RuntimeException? Где его поймали и обработали? И кто?
Ещё
Автор: nikov
Дата: 07.08.08

Код там был такой: using (file1 = ...) using(file2 = ...) using(file3 = ...) { ... }
Каждый файл в Dispose кинул исключение.

D>Чушь. Все кидают, только шум стоит. И никаких проблем. Потому что ничего не "затирается", а ловится и обрабатывается.


Ссылка выше.

D>В C# нет раскрутки стека, и код, за исключением finalizer'ов, исполняется в обычном контексте. Мне вот непонятно где можно использовать, даже если и есть... Разве что на уровне MSIL уже...


Причём тут раскрутка стека. Функция даже называется uncaught_exception.
В C#, как видим, возможна ситуация, когда код выполняется в процессе полёта исключения, можно ли определить в этом самом коде, что в данный момент летит исключение?
Re[23]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 08.08.08 14:36
Оценка:
Здравствуйте, eao197, Вы писали:

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

E>Думаю, все еще проще -- вы не понимаете, почему в C++ вызывается terminate(),

Опять с ног на голову. Это оппоненты не понимают, как можно было убедиться по рассказам о "недодеструкченности" и "затирании"...
А лично я отлично понимаю, что комитет принял решение о terminate() совершенно неспроста, и на базе серьёзных оснований. И именно поэтому эти самые основания меня и интересуют...

E>поэтому C++ отстой, а вы весь такой в белом.


Ну причём здесь я-то ??? В белом C#
Re[24]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 08.08.08 18:28
Оценка:
Здравствуйте, IB, Вы писали:

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

IB>Не просто предыдущее, а с полным сохранением стека, то есть, можно проследить оригинальное место возникновения исключения, как буд-то ни какого catch-а не было.
Да, это преимущество. Хотя, в С++ при выбросе второго исключения тоже можно будет проследить место выброса первого.

По crash-dump'у.

C>>Не совсем согласен, что оно существенное.

IB>Нормальный ход — ты утверждаешь, что исключение при перехвате проглатывается, но замечание о том, что, на самом деле, оригинальное исключение в том или ином виде может быть доступно выше по стеку ты находишь не существенным...
Оно не доступно напрямую (в catch). Но его можно выковырять при желании.

Вот если был бы полноценный catch с учётом вложенных исключений (паттерн-матчинг?), то тогда полностью был бы согласен.
Sapienti sat!
Re[32]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 08.08.08 21:46
Оценка:
Здравствуйте, VoidEx, Вы писали:

D>>Основания очевидные. Если какой-то деструктор всё-таки бросает исключения, то любая раскрутка стека с автоматическим объектом этого типа и сразу terminate() Остаётся вариант с проверкой uncaught_exception(), однако при нём мы получаем неконсистентное поведение — исключение может быть, а может и не быть...

VE>В C# мы получаем поведение — исключение вылетит, но может затереть то, которое уже летит.

Нет никакого "затереть". Всё под контролем программиста. Можно, например, поймать всё что пролетает через функцию, сложить в своё специальное исключение, и на выходе получить вообще все цепочки исключений попавших внутрь функции за период её исполнения, со всеми stacktrace'ами и прочим добром.

И делается это одним движением, и без малейших напрягов. Для C++ же Вы вот уже пробовали написать аналогичный функционал. Как успехи с доточкой ???

VE>В C++ долетает только то, что вылетело первым, последующие — не бросаются.

VE>Совпадение и разница видны?

Конечно видна. В С++ все остальные исключения за пределами деструктора просто отсутствуют, их нет вообще.

VE>Предлагаю заюзать коды возврата и писать код, бо именно это вы и предлагаете.


Не получится. У кода возврата нет stacktrace'а, нет InnerException'а, он не пробрасывается по стеку вызовов, и не попадает в try/catch'и сотоварищи...

VE>Толку от исключений, если каждый диспоз надо так обложить.


См. выше.

D>>Чушь. В C++ вызов деструктора автоматического объекта обернуть в try-catch невозможно. Если Вы это отрицаете — показывайте пример.

VE>Только не надо пытаться придраться, что я обрабатываю и конструктор тоже.

Что значит "не надо" ??? Я просил Вас обернуть вызов деструктора, кузне... тьфу... конструктор мне не нужен.

VE>Сначала сравните код.


Гы А зачем ? Я косяки в постинге Sinclair'а заметил сразу (он сейчас код редко пишет, подотвык уже )

"Но в главном-то он прав" (с) не мой

Смотрите как надо:
    var file1 = new File(...);
    try
    {
        //
    }
    finally
    {
        try
        {
            file1.Dispose();
        }
        catch (Exception ex) { }
    }

Идея понятна ?

VE>>>Вам привели пример, когда долетает только последнее исключение, где предыдущее?

D>>Оно было поймано и обработано. Это try/catch, а не "затирание".
VE>Здесь
Автор: Cyberax
Дата: 08.08.08
приведён код.

VE>Куда улетело RuntimeException? Где его поймали и обработали? И кто?

Его поймала и обработала секция finally. Бо "внизу" она, как и catch, является handler block'ом.

D>>Чушь. Все кидают, только шум стоит. И никаких проблем. Потому что ничего не "затирается", а ловится и обрабатывается.

VE>Ссылка выше.

Вы не поняли. Я говорю о том, что стандартные библиотеки кидают исключения из close() и им подобным.

VE>Причём тут раскрутка стека.


При том, что в C++ понятно где использовать сие сакральное знание. А вот зачем оно в C# ? Там нет этих автоматических ужасов.

VE>В C#, как видим, возможна ситуация, когда код выполняется в процессе полёта исключения,


См. выше. Это эквивалент (почти) catch'а.

VE>можно ли определить в этом самом коде, что в данный момент летит исключение?


Зачем ? Если нужна обработка при исключении — напишите явный catch.
Re[2]: Зачем нужен сборщик мусора? Как жить без деструкторов
От: Кэр  
Дата: 09.08.08 12:16
Оценка:
Здравствуйте, Adriano, Вы писали:

A>
A>Connection conn = getConnection();
A>try {
A>  //че-то делаем
A>  ....
A>}
A>finally {
A>  conn.close();
A>}
A>

A>Примеры взял из книжки по яве, которая лежит у меня на столе (Кей. С. Хорстман, Библиотека профессионала. Java 2). Посмотрим теперь плагины из Eclipse — увидим примерно тоже самое: файлы и соединения закрываются без проверки результата. Найдем участки кода из Windows или Linux — то же самое, мьютексы освобождается без проверки! Оказывается существуют случаи, и это абсолютное большинство случаев, когда не нужно проверять результат уничтожения ресурса. И хочу заметить, что Windows, Linux, Eclipse – это очень серьезные проекты, которые созданы далеко не дилетантами. И почему-то мне кажется, что даже drol, котоырй так активно утверждает, что надо проверять все и везде, на самом деле закрывает файл “немой” строкой file.close();

Паттерн using в C# проверяет объект на равенство нулю перед вызовом Dispose. Все остальные проверки могут быть только семантического рода и к паттернам уже не имеют никакого отношения. В C# есть требование, что вызов Dispose для неоткрытого ресурса не должен вызывать проблем. Точно такое же требование нужно предъявлять и деструкторам в С++, коли уж вам так хочется упихать туда очистку любых ресурсов.
Более того, мне непонятно, а какое премущества, кроме недостатков, мы имеем с передачей объекта ресурса в другой метод по ссылке? Тут уж явно нужно звать delete, который ничем принципиально не отличается от вызова метода Dispose, за исключением отсутствия возможности выбросить исключение и отсутствия поддержки IDE (студия, при наличии R#, начинает волновать, если где-то используется IDisposable объект без using или вызова Dispose).

A>Бывают случаи, когда необходимо контролировать уничтожение ресурса и реагировать на различные ошибки. Это встречается гораздо реже, но встречается. В этом случае деструктор — не лучший вариант.


Это встречаются реже, потому что большая часть деструкторов чистит ресурс "память". Когда чиститься любой другой ресурс — исключение нам нужно всегда. Неважно на каком языке вы пишите.
Если вам нужен надежный клиент — обернете по месту try/catch — и добавите любую логику по вкусу (сразу замечу, что пихать любую логику по вкусу на место проишествия — в деструктор дурная затея).
Но чаще всего совсем каждый вызов оборачивать в try/catch не нужно — достаточно обрамлять большие смысловые блоки. Главное получить exception со всеми подробностями, когда исключительное состояние возникнет. Чтобы сэкономить уйму времени на идентификацию проблемы, когда она возникнет, к примеру, у клиента на Аляске (с клиентом на Аляске вам сильно аукнется "надежный" код, глотающий исключения, при очистке ресурсов).
Re[27]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 09.08.08 14:14
Оценка:
Здравствуйте, Cyberax, Вы писали:

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

C>Вложенные исключения — вполне очевидно, что работают нормально. Я говорю только про вылетающие за пределы деструктора исключения.

Так вот я и спрашиваю: в чём проблема с остальными ? Почему нельзя делать так же как с исходным исключением, и так же как с обложенными try/catch'ами ?

D>>Чушь. Никто ничего не заменяет. try/finally это по-факту синтаксический сахар на базе try/catch/throw, то есть обычной обработки исключения с его возможным "пробросом". Если Вы обложите try/catch'ем содержимое finally-блока, то на выходе получите свой любимый RuntimeException. А вот теперь попробуйте сделать то же самое с вызовом деструктора автоматического объекта в C++...

C>Покажи код.

Что показать ? Как сделать finally через try/catch/throw ? Например, вот так:
try {
  //
} catch {
  // finally code
  throw;
}

{
  // finally code
}

*Там, конечно, есть тонкости, бо try/catch/обычный блок есть более широкие конструкции, и нужно следить за содержимым // finally code. Чтобы return'ов не было и т.п.

C>>>В C++ в этом случае для надёжности решили делать std::terminate.

D>>Ну всё, приехали, terminate==надёжность... Даже не знаю что и сказать-то. Разве что порекомендовать почитать БСЭ на тему... раз эдак семь.
C>Да, это надёжность. Рекомендую прочитать про http://en.wikipedia.org/wiki/Fail-safe . Решение с std::terminate как раз является таковым.

Гы Спасибо, хоть не русскую wikipedia порекомендовали...

Но тем не менее сгодится. И так смотрим статью, что там нас интересует ? Ага, раздел Electrical or electronic.

The automatic protection of programs and/or processing systems when a hardware or software failure is detected in a computer system. See fail-safe (computer).

Идём по ссылке. Читаем:

In engineering, Fault-tolerant design, also known as fail-safe design, is a design that enables a system to continue operation, possibly at a reduced level (also known as graceful degradation), rather than failing completely, when some part of the system fails.


Дальнейшие комментарии нужны ?

*Учитесь читать...

C>>>Существует. Выполнение блоков finally — ну абсолютно то же самое. Оно даже внутри реализовано так же.

D>>См. выше. try/finally в этом моменте реализован через try/catch. Никакой раскрутки здесь нет.
C>Да? Ну совсем нет?

Да. Совсем нет. Бо раскрутка стека, опять-таки согласно стандарту С++, есть:

The process of calling destructors for automatic objects constructed on the path from a try block to a
throw-expression is called “stack unwinding.”


И, за отсутствием автоматических объектов с деструкторами, "раскрутки" в C# по-определению быть не может. И его спецификация полностью со мной согласна. В ней эти термины не встречаются
*Читайте стандарты, они рулез
Re[24]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 09.08.08 16:02
Оценка:
Здравствуйте, drol, Вы писали:

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

E>>Думаю, все еще проще -- вы не понимаете, почему в C++ вызывается terminate(),

D>Опять с ног на голову. Это оппоненты не понимают, как можно было убедиться по рассказам о "недодеструкченности" и "затирании"...

D>А лично я отлично понимаю, что комитет принял решение о terminate() совершенно неспроста, и на базе серьёзных оснований. И именно поэтому эти самые основания меня и интересуют...

Недодеструкченность таки присутствует:
class A {
  public: ...
    ~A() { if(some_condition) throw some_error(); }
  ...
};
class B {
  public: ...
    ~B() { cleanup_some_important_resource(); }
    ...
};

class C {
  private :
    A m_a;
    B m_b;
  ...
}

Если при разрушении объекта типа C деструктор m_a выбросит исключение, то деструктор m_b не будет вызван. Вот и недодеструкченность.

Чтобы ее избежать, в C++ пришлось бы оборачивать вызов любого деструктора в try..catch, т.е. что-то типа:
void C::__destroy_C_object() {
  // Сначала деструктор C.
  try { this->~C(); } catch( ... ) { ... }
  // Потом деструктор m_a.
  try { this->m_a.~A(); } catch( ... ) { ... }
  // Потом деструктор m_b.
  try { this->m_b.~B(); } catch( ... ) { ... }
}

А теперь попробуйте подсчитать оверхед, который будет нести с собой подобные скобки try/catch на каждый деструктор. И это при том, что в C++ деструкторы вызываются на несколько порядков чаще, чем Dispose в C#.

Это, имхо, одна из возможных причин.
Хотя реальные причины мог бы озвучить, разве что, сам Страуструп.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[25]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 09.08.08 18:05
Оценка:
Здравствуйте, eao197, Вы писали:

E>>>Думаю, все еще проще -- вы не понимаете, почему в C++ вызывается terminate(),


D>>Опять с ног на голову. Это оппоненты не понимают, как можно было убедиться по рассказам о "недодеструкченности" и "затирании"...

D>>А лично я отлично понимаю, что комитет принял решение о terminate() совершенно неспроста, и на базе серьёзных оснований. И именно поэтому эти самые основания меня и интересуют...

E>Недодеструкченность таки присутствует:

E>Если при разрушении объекта типа C деструктор m_a выбросит исключение, то деструктор m_b не будет вызван. Вот и недодеструкченность.

Ещё один "писатель"...

Да нормально всё будет в Вашем примере.

Во-первых, потому что деструктор для m_b вызовется до деструктора m_a. Бо объявлен в классе позже.
А во-вторых, даже если поменять порядок объявлений, то всё равно деструктор для m_b вызовется. Потому как после исключения начнётся раскрутка стека, и в ней, разумеется, будет вызов этого самого деструктора.

"Недодеструкченность" же о которой шла речь, это неисполнение кода внутри деструктора; кода оставшегося "за пределами" после возникновения исключения.

*Прежде чем постить примерчеги, рекомендуется их позапускать хотя бы пару раз... Помогает избежать

E>Чтобы ее избежать, в C++ пришлось бы оборачивать вызов любого деструктора в try..catch, т.е. что-то типа:


Так вот оно и "оборачивается". Есть таблицы вызовов деструкторов автоматических объектов/данных-членов. Только механизма работает всего лишь до второго исключения из деструктора почему-то О чём и вопрос, собственно...

E>Хотя реальные причины мог бы озвучить, разве что, сам Страуструп.


Не знаю насчёт БС, но вот Вам точно не светит их когда-либо озвучить...
Re[25]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 09.08.08 18:56
Оценка:
Здравствуйте, eao197, Вы писали:

E>Недодеструкченность таки присутствует:


Можно подтверждение из стандарта? А то в 9-й студии вызываются и базовые деструкторы и деструкторы мемберов без каких-либо проблем. Останавливается только деструктор самого объекта.
Re[33]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 09.08.08 19:32
Оценка:
Здравствуйте, drol, Вы писали:

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


D>Нет никакого "затереть". Всё под контролем программиста. Можно, например, поймать всё что пролетает через функцию, сложить в своё специальное исключение, и на выходе получить вообще все цепочки исключений попавших внутрь функции за период её исполнения, со всеми stacktrace'ами и прочим добром.


...

D>И делается это одним движением, и без малейших напрягов. Для C++ же Вы вот уже пробовали написать аналогичный функционал. Как успехи с доточкой ???


В моём "примере", извините, всё делалось автоматом, без расстановки новых try-catch. Если это несущественно, то и говорить не о чем.

D>Конечно видна. В С++ все остальные исключения за пределами деструктора просто отсутствуют, их нет вообще.


...

D>"Но в главном-то он прав" (с) не мой


D>Смотрите как надо:

D>
D>    var file1 = new File(...);
D>    try
D>    {
D>        //
D>    }
D>    finally
D>    {
D>        try
D>        {
D>            file1.Dispose();
D>        }
D>        catch (Exception ex) { }
D>    }
D>

D>Идея понятна ?

Да. Автоматизм где? Ручками все умеют.
А два файла? Два try-catch внутри finally?

file f;
try
{
}
catch ( ... )
{
}
f.close();


D>Его поймала и обработала секция finally. Бо "внизу" она, как и catch, является handler block'ом.


Стоп.

try
{
  f1(); // throws
}
finally
{
  // Тут как понять, что летит исключение?
}


Если внутри finally сделать throw, то полетит новое исключение, если не сделать — то оригинальное (которое вылетело из f1()).
Соответственно, если обламалась попытка освободить ресурс — швыряем исключение, при этом старое пропадает. Но так как у вас "все на совести программиста", вы предлагаете писать так (для сохранения оригинального исключения):


try
{
  f1(); // throws
}
catch // try throwed
{
  // cleanup without throw
  throw; // rethrow original exception
}
// try not throwed
// cleanup with throw


Э? И чем это лучше вот этого:

my::~my()
{
  // cleanup
  if (!std::uncaught_exception())
    throw ...;
}


Я имею такие же основания утверждать, что в Си++ всё на совести программиста, и если вы хотите затереть(вычеркнуто) обработать старое исключение, то пишите так:

file f; // destructor may throw (only if !std::uncaught_exception)
try
{
}
catch ( ... )
{
  f.close(); // throws new exception
}
// destructor throws new exception


Если вы всё ещё не видите, что в C# и C++ есть краткозаписывамое решение "по умолчанию" (затирать старое исключение и не кидать нового соответственно) и есть способ сделать наоборот ручками (причем способы аналогичны), но продолжать дискуссию не имеет смысла.

VE>>Причём тут раскрутка стека.


D>При том, что в C++ понятно где использовать сие сакральное знание. А вот зачем оно в C# ? Там нет этих автоматических ужасов.


При автоматическом освобождении там есть ужас затирания исключения.
Выход — обкладывать все try-catch'ами или писать как в вашем примере (ручками звать Dispose).
Оба метода применимы и в Си++.

D>Зачем ? Если нужна обработка при исключении — напишите явный catch.


void foo()
{
  // летит ли сейчас исклчюение? т.е. если я брошу - затру ли я его?
}


На место комментария вставьте, пожалуйста, код, который определит мне, летит ли исключение.
Re[34]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 09.08.08 19:36
Оценка:
Здравствуйте, VoidEx, Вы писали:

Важный момент, finally сам за меня решает, как обработать летящее исключение, — это просто проигнорировать. Си++ этого не делает, потому игнорировать (не кидать новое исключение при уже летящем) решает сам программист.
И то, и другое — два разных решения, а не "C++ в говне, а C# в белом".
Re[34]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 09.08.08 22:19
Оценка: -4
Здравствуйте, VoidEx, Вы писали:

D>>И делается это одним движением, и без малейших напрягов. Для C++ же Вы вот уже пробовали написать аналогичный функционал. Как успехи с доточкой ???


VE>В моём "примере", извините, всё делалось автоматом, без расстановки новых try-catch. Если это несущественно, то и говорить не о чем.


Гы В Вашем примере try/catch вообще не работает. Автоматчик... Так что либо дотачивайте, либо "слив засчитан"

VE>Да. Автоматизм где?


Передёргивать не надо, уважаемый Речь не о выдуманном Вами каком-то там "автоматизме", а о try/catch'е вокруг вызова деструктора автоматического объекта.

VE>Ручками все умеют.


Не умеете. А если считаете что умеете, тогда кончайте вилять, и давайте показывайте обёртку вызова деструктора автоматического объекта try/catch'ем, иначе "слив засчитан 2"

VE>А два файла? Два try-catch внутри finally?


Разумеется, нет. На каждый ресурс должен быть свой try/finally. Не нужно в кучу мешать...

VE>
VE>file f;
VE>try
VE>{
VE>}
VE>catch ( ... )
VE>{
VE>}
VE>f.close();
VE>

Это вообще к чему и про что

VE>Если внутри finally сделать throw, то полетит новое исключение, если не сделать — то оригинальное (которое вылетело из f1()).

VE>Соответственно, если обламалась попытка освободить ресурс — швыряем исключение, при этом старое пропадает. Но так как у вас "все на совести программиста", вы предлагаете писать так (для сохранения оригинального исключения):

Ничего не понял Вы хотите пробросить из finally исходное исключение ? Ну так я же выше показал как это делать: оборачиваете внутренности finally в try/catch.

VE>Э? И чем это лучше вот этого:


Не знаю. Я не понимаю, зачем Вы оба этих куска кода написали. Тезис какой ? Чего хотите ?

VE>Я имею такие же основания утверждать, что в Си++ всё на совести программиста, и если вы хотите затереть(вычеркнуто) обработать старое исключение, то пишите так:


Не имеете. Бо исключение из деструктора при раскрутке стека => terminate() В схеме же с try/finally из Java/C# проблем такого рода нет.

VE>
VE>file f; // destructor may throw (only if !std::uncaught_exception)
VE>try
VE>{
VE>}
VE>catch ( ... )
VE>{
VE>  f.close(); // throws new exception
VE>}
VE>// destructor throws new exception
VE>

Какой ещё close() ??? Ваш тезис — освобождение ресурса в деструкторе. Вот и освобождайте там. А close() это мой тезис, а не Ваш.

D>>При том, что в C++ понятно где использовать сие сакральное знание. А вот зачем оно в C# ? Там нет этих автоматических ужасов.


VE>При автоматическом освобождении там есть ужас затирания исключения.


Нет никакого "затирания". Есть пойманное и обработанное finally исключение.

VE>Выход — обкладывать все try-catch'ами или писать как в вашем примере (ручками звать Dispose).


Если требуется более сложная логика обработки исключений — она будет реализована именно так.

VE>Оба метода применимы и в Си++.


Гы В случае использования аналога IDisposable/try/finally, конечно применимы!!! В случае же очистки ресурса в деструкторе — обломс.

VE>
VE>void foo()
VE>{
VE>  // летит ли сейчас исклчюение? т.е. если я брошу - затру ли я его?
VE>}
VE>

Опять двадцать пять. Да не затирает никто, ничто, никого и ничего. Исключения сохраняются на стеке. А потом ловятся где-то там наверху.

Ну зачем Вашей foo() знать, в каких условиях произошёл вызов ??? Это не её проблемы. Кто вызывает, тот и заботится о том, нужно ему исключение или нет. Для того исключения и придумали, чтобы передвинуть обработку от точки их возникновения, да на тот уровень стека вызовов, который знает что делать в этом случае. А Вы опять пытаетесь засунуть всё обратно в самый низ...
*И эти люди пишут на C++...
Re[35]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 10.08.08 02:29
Оценка: +2
Здравствуйте, drol, Вы писали:

Извините, но продолжать с вами разговор я больше не хочу.
Упирайтесь рогом перед зеркалом и хамите туда же.
Re[34]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.08.08 04:59
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Стоп.


VE>
VE>try
VE>{
VE>  f1(); // throws
VE>}
VE>finally
VE>{
VE>  // Тут как понять, что летит исключение?
VE>}
VE>

Не надо там понимать ничего. finally нужен чтобы код выполнялся в любом случае, там абсолютно пофиг было исключение или нет.

VE>Если внутри finally сделать throw, то полетит новое исключение, если не сделать — то оригинальное (которое вылетело из f1()).

VE>Соответственно, если обламалась попытка освободить ресурс — швыряем исключение, при этом старое пропадает.


    static void Main()
    {
        try
        {
            throw new Exception("Исключение 1");
        }
        finally
        {
            throw new Exception("Исключение 2");
        }


Запустите этот код, будете удивлены.
Re[35]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 10.08.08 05:34
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>
G>    static void Main()
G>    {
G>        try
G>        {
G>            throw new Exception("Исключение 1");
G>        }
G>        finally
G>        {
G>            throw new Exception("Исключение 2");
G>        }   
G>


G>Запустите этот код, будете удивлены.


Ну поймало исключение 2, если не ловить, то окошко с исключением 2.
Я это должен был увидеть?
Re[36]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.08.08 06:33
Оценка:
Здравствуйте, VoidEx, Вы писали:

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


G>>
G>>    static void Main()
G>>    {
G>>        try
G>>        {
G>>            throw new Exception("Исключение 1");
G>>        }
G>>        finally
G>>        {
G>>            throw new Exception("Исключение 2");
G>>        }   
G>>


G>>Запустите этот код, будете удивлены.


VE>Ну поймало исключение 2, если не ловить, то окошко с исключением 2.

VE>Я это должен был увидеть?
У меня в консоли выводятся оба ексепшена.
Re[26]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 10.08.08 06:41
Оценка:
Здравствуйте, drol, Вы писали:

D>А во-вторых, даже если поменять порядок объявлений, то всё равно деструктор для m_b вызовется. Потому как после исключения начнётся раскрутка стека, и в ней, разумеется, будет вызов этого самого деструктора.


Ух ты, оказывается C++ и так умеет! Здорово.
Никогда не сталкивался с исключениями в деструкторах, поэтому не знал, что C++ дает такие гарантии.

E>>Чтобы ее избежать, в C++ пришлось бы оборачивать вызов любого деструктора в try..catch, т.е. что-то типа:


D>Так вот оно и "оборачивается". Есть таблицы вызовов деструкторов автоматических объектов/данных-членов. Только механизма работает всего лишь до второго исключения из деструктора почему-то О чём и вопрос, собственно...


Ну попробуйте ответить на вопрос: порождается исключение A, начинается раскрутка стека. В процессе которой выбрасывается еще N исключений B1..Bn. Какое из исключений (A,B1,...,Bn) должно быть видно в программе?

E>>Хотя реальные причины мог бы озвучить, разве что, сам Страуструп.


D>Не знаю насчёт БС, но вот Вам точно не светит их когда-либо озвучить...


Да я и не претендовал


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[37]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 10.08.08 07:32
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>У меня в консоли выводятся оба ексепшена.


Пардон. У меня было оконное (может и в нём? Просто не заметил?)
Но вопрос в другом. В finally может быть уже летящее исключение, а может и не быть.
Я хочу кинуть новое, если никакого не летит, и хочу оставить изначальное, если оно в полёте. Предложенный drol'ом try-catch внутри finally не сработает, ибо тогда летит только изначальное исключение из try (если вообще летит).

Вообще, считаю, что в случае Си++ надо писать:

file f1, f2, f3;
foo();
bar();
f1.close(); f2.close(); f3.close();


Если foo-bar пройдут нормально, то получим исключение при ошибки записи в файл, если foo кинет исключение, то закрытие будет производиться уже деструкторами — молча, но ничего от этого мы не потеряем, так как исключение всё же будет поймано и обработано (хотя и другое, то, которое вылетело изначально).
Re[37]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: nikov США http://www.linkedin.com/in/nikov
Дата: 10.08.08 09:07
Оценка: 7 (2)
Здравствуйте, gandjustas, Вы писали:

G>У меня в консоли выводятся оба ексепшена.


Тут срабатывает совсем другой сценарий. Дело в том, что обработчик UnhandledException у домена вызывается раньше, чем выполняются блоки finally вокруг места выброса исключения. Если бы мы ловили исключения выше по стеку, то мы поймали бы только "Исключение 2", а "Исключение 1" было бы потеряно. Так и в стандарте C# написано:

8.10 The try statement
....
If an exception is thrown during execution of a finally block, and is not caught within the same finally block, the exception is propagated to the next enclosing try statement. If another exception was in the process of being propagated, that exception is lost.


Кстати, эта формулировка была внесена в стандарт по моему предложению.
Re[38]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.08.08 10:40
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Но вопрос в другом. В finally может быть уже летящее исключение, а может и не быть.

Для этого он и придуман.

VE>Я хочу кинуть новое, если никакого не летит, и хочу оставить изначальное, если оно в полёте. Предложенный drol'ом try-catch внутри finally не сработает, ибо тогда летит только изначальное исключение из try (если вообще летит).

А зачем вам тогда try/finally ? Бросайте исключение сразу после выполнения операции.

VE>Вообще, считаю, что в случае Си++ надо писать:


VE>
VE>file f1, f2, f3;
VE>foo();
VE>bar();
VE>f1.close(); f2.close(); f3.close();
VE>


VE>Если foo-bar пройдут нормально, то получим исключение при ошибки записи в файл, если foo кинет исключение, то закрытие будет производиться уже деструкторами — молча, но ничего от этого мы не потеряем, так как исключение всё же будет поймано и обработано (хотя и другое, то, которое вылетело изначально).


А чем хуже писать^
using (var f1 = new file())
using (var f2 = new file())
using (var f3 = new file())
{
    foo();
    bar();
}

Поведение будет такоеже. Только все Dispose гарантированно вызовутся, деструкторы не нужны будут.
Может я что-то не ак понял?
Re[38]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 10.08.08 10:41
Оценка:
Здравствуйте, nikov, Вы писали:

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


G>>У меня в консоли выводятся оба ексепшена.


N>Тут срабатывает совсем другой сценарий. Дело в том, что обработчик UnhandledException у домена вызывается раньше, чем выполняются блоки finally вокруг места выброса исключения. Если бы мы ловили исключения выше по стеку, то мы поймали бы только "Исключение 2", а "Исключение 1" было бы потеряно. Так и в стандарте C# написано:


N>

N>8.10 The try statement
N>....
N>If an exception is thrown during execution of a finally block, and is not caught within the same finally block, the exception is propagated to the next enclosing try statement. If another exception was in the process of being propagated, that exception is lost.


N>Кстати, эта формулировка была внесена в стандарт по моему предложению.


А каким образом UnhandledException узнает о двух исключениях?
Re[36]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 10.08.08 11:36
Оценка: -1
Здравствуйте, VoidEx, Вы писали:

VE>Извините, но продолжать с вами разговор я больше не хочу.


Ещё бы. Ведь дело дошло до реального скилла, код писать надо, а не только словеса копи-пастить...

"Слив засчитан"
Re[27]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 10.08.08 11:40
Оценка:
Здравствуйте, eao197, Вы писали:

E>Ну попробуйте ответить на вопрос: порождается исключение A, начинается раскрутка стека. В процессе которой выбрасывается еще N исключений B1..Bn. Какое из исключений (A,B1,...,Bn) должно быть видно в программе?


Ответ очевидный: должны быть видны все. Пойматься же должно в первом catch'е подходящем под какое-нибудь из цепочки. Раскрутка стека также должна нормально дорабатывать.

Вобщем как-то так...
Re[39]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: nikov США http://www.linkedin.com/in/nikov
Дата: 10.08.08 13:33
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>А каким образом UnhandledException узнает о двух исключениях?


Он вызывается два раза.
Re[39]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 10.08.08 17:56
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>А чем хуже писать^

G>
G>using (var f1 = new file())
G>using (var f2 = new file())
G>using (var f3 = new file())
G>{
G>    foo();
G>    bar();
G>}
G>

G>Поведение будет такоеже. Только все Dispose гарантированно вызовутся, деструкторы не нужны будут.
G>Может я что-то не ак понял?

Ничем не хуже. Но в этом коде вылетит то исключение, которое будет выброшено последним. В коде Си++ то, которое вылетело первым (так как деструкторы уже не бросят).
drol утверждает, что Си++ в этом плане "отстой", а C# "рулит".
Показать ему, что это две стороны одной медали, мне не удалось. Он перешёл на хамство и мы закончили диалог.
Re[40]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 10.08.08 19:56
Оценка: -1
Здравствуйте, VoidEx, Вы писали:

VE>Ничем не хуже. Но в этом коде вылетит то исключение, которое будет выброшено последним.


Если Вам нужны другие исключения — пишите явный код на try/finally/catch/throw. И они у Вас будут безо всяких особых приседаний.

VE>В коде Си++ то, которое вылетело первым (так как деструкторы уже не бросят).


В случае C++ других исключений нет вообще.

В этом и разница. В C# можно элементарным образом получить хоть все цепочки исключений возникших в методе, а в C++ только одно, самое первое исключение.

VE>drol утверждает, что Си++ в этом плане "отстой", а C# "рулит".


Врёте. Мой тезис — не надо пихать нетривиальную очистку ресурса в деструктор.
Re[41]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 10.08.08 20:39
Оценка: 33 (1)
Здравствуйте, drol, Вы писали:

Я с вами уже прекратил разговор. Я взял за правило не спорить с женской логикой, в которой целью стоит сказать последние слова типа "слив защитан" и считать себя после этого "победителем" в непонятно какой войне.
Re[41]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 10.08.08 20:41
Оценка:
Здравствуйте, drol, Вы писали:

D>В этом и разница. В C# можно элементарным образом получить хоть все цепочки исключений возникших в методе, а в C++ только одно, самое первое исключение.


В качестве домашнего упражнения:
Дана функция foo(), поймайте мне всю цепочку исключений, из неё вылетающих.
Отвечайте, когда сможете это сделать, остальное я буду игнорировать, мне надоело.
Re[42]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 10.08.08 21:23
Оценка: :)
Здравствуйте, VoidEx, Вы писали:

VE>Я с вами уже прекратил разговор.


А я с Вами ещё не закончил, уважаемый.

Так вот, если Вы желаете сослаться на какое-либо моё утверждение, то, пожалуйста, цитируйте его дословно, с контекстом, и с указанием прямой ссылки на соответствующий постинг. Бо я очень раздражаюсь, когда перевирают мои слова, и приписывают мне какие-то левые домыслы
Re[42]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 10.08.08 21:48
Оценка: -1
Здравствуйте, VoidEx, Вы писали:

D>>В этом и разница. В C# можно элементарным образом получить хоть все цепочки исключений возникших в методе, а в C++ только одно, самое первое исключение.


VE>Дана функция foo(), поймайте мне всю цепочку исключений, из неё вылетающих.


Гы Вылететь из функции может только одно единственное исключение. >1 их может возникнуть внутри функции, когда мы ловим их try/catch/finally/using. Для реализации моего утверждения, функция должна сложить все эти пойманные исключения в новое, отдельное, специальное исключение, и, в конце-концов, бросить его.

Если концепция Вам до сих пор непонятна, то вечером продемонстрирую...
Re[43]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 10.08.08 21:56
Оценка:
Здравствуйте, drol, Вы писали:

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


VE>>Я с вами уже прекратил разговор.


D>А я с Вами ещё не закончил, уважаемый.


D>Так вот, если Вы желаете сослаться на какое-либо моё утверждение, то, пожалуйста, цитируйте его дословно, с контекстом, и с указанием прямой ссылки на соответствующий постинг. Бо я очень раздражаюсь, когда перевирают мои слова, и приписывают мне какие-то левые домыслы


В C# можно элементарным образом получить хоть все цепочки исключений возникших в методе, а в C++ только одно, самое первое исключение


Я уже привёл задачу. Меня не волнует, сколько из функции вылетает. Я выделил ключевые слова.
Без изменения функции этого сделать невозможно. Либо вы утверждаете обратное и приводите код, это подтверждающий, либо тогда признаёте, что были неправы. Имея доступ к коду функции, всю цепочку можно получить и в Си++, опровергайте тоже кодом, который будет принципиально неосуществим в Си++.
Re[43]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Adriano  
Дата: 10.08.08 22:16
Оценка:
Здравствуйте, drol, Вы писали:

D>Врёте. Мой тезис — не надо пихать нетривиальную очистку ресурса в деструктор.


равно как и не надо пихать нетривиальную очистку ресурса в одинокий finally


some_obj.open();
try {
  .....
  throw new VeryVeryVeryVeryImpotantException(); //которое ждут выше
  .....
}
finally {
  some_obj.close();//throw new OrdinaryException();
}



D>Если Вам нужны другие исключения — пишите явный код на try/finally/catch/throw. И они у Вас будут безо всяких особых приседаний.

этот случай — универсальный, и похоже реализуется во всех языках, тут говорить неочем.

Остается битва титанов(на тнт): Деструктор VS finally-одиночка
Ни первое, ни второе не подходит для нетривиальной очистки ресурса
Тут можно ставить точку.

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

зы
считаю освобождение мьютекса — тривиальной, т.к. из user mode его теоретически невозможно повредить, тут нельзя выдернуть флешку как в случае с файлом
Re[30]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 11.08.08 06:53
Оценка:
Здравствуйте, drol, Вы писали:

D>Конечно приводит, бо у Вас там два объекта. При выходе из блока вызывается деструктор для b. В нём происходит исключение. Стартует раскрутка стека. Она вызывает деструктор a. И в нём тоже происходит исключение. Только на сей раз это исключение при раскрутке стека, и строго согласно стандарту следует terminate()

Ну а где гарантии что в реальной программе такого не произойдет? Никаких — значит нафиг.

D>Если в Вашем примере оставить только один объект — всё будет нормально. То бишь "недодеструкченный" объект + продолжающая работать как ни в чём не бывало программа.

Т.е. в тепличных условиях может и будет работать.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[28]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 11.08.08 07:04
Оценка:
Здравствуйте, drol, Вы писали:

E>>Ну попробуйте ответить на вопрос: порождается исключение A, начинается раскрутка стека. В процессе которой выбрасывается еще N исключений B1..Bn. Какое из исключений (A,B1,...,Bn) должно быть видно в программе?


D>Ответ очевидный: должны быть видны все.


Тогда может быть вы объясните, как это можно сделать, например, в следующем случае:
class B {
  public : ...
    ~B() { if(some_condition) throw some_exception_t(); }
};

class C {
  B m_b[ 10240 ];
  ...
};

void f() {
  std::auto_ptr< C > c( new C() );
  ...
  if( something_failed )
    throw another_exception_t();
}


При раскрутке стека начнут вызываться деструкторы для 10K объектов B. Каждый из них выбрасывает свое исключение. Куда их все помещать? А что делать, если при их сохранении заканчивается свободная память?

D>Пойматься же должно в первом catch'е подходящем под какое-нибудь из цепочки.


Возвращаясь к тому же самому примеру. Функция f() вызывается из функции:
void d() {
  try {
    f();
  }
  catch( const some_exception_t & x ) {
    ...
  }
}

Допустим, что при раскрутке стека все исключения удалось сохранить и есть множество исключений, состоящее из одного исключения another_exception_t и 10K исключений some_exception_t. Для какого из экземпляров some_exception_t должен сработать catch в d()? Что делать с остальными экземплярами?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[40]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 11.08.08 08:34
Оценка:
Здравствуйте, VoidEx, Вы писали:

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


G>>А чем хуже писать^

G>>
G>>using (var f1 = new file())
G>>using (var f2 = new file())
G>>using (var f3 = new file())
G>>{
G>>    foo();
G>>    bar();
G>>}
G>>

G>>Поведение будет такоеже. Только все Dispose гарантированно вызовутся, деструкторы не нужны будут.
G>>Может я что-то не ак понял?

VE>Ничем не хуже. Но в этом коде вылетит то исключение, которое будет выброшено последним. В коде Си++ то, которое вылетело первым (так как деструкторы уже не бросят).

VE>drol утверждает, что Си++ в этом плане "отстой", а C# "рулит".
VE>Показать ему, что это две стороны одной медали, мне не удалось. Он перешёл на хамство и мы закончили диалог.

VE>file f1, f2, f3;
VE>foo();
VE>bar();
VE>f1.close(); f2.close(); f3.close();
VE>

В вашем коде, если деструктор file вызывает close, и в нем может вылетет exception, то программа вообще может аварийно завершиться.
Если деструктор не вызывает close, то фактически ресурс (файл) окажется незакрытым.
Re[41]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 11.08.08 09:39
Оценка:
Здравствуйте, gandjustas, Вы писали:

VE>>Ничем не хуже. Но в этом коде вылетит то исключение, которое будет выброшено последним. В коде Си++ то, которое вылетело первым (так как деструкторы уже не бросят).

VE>>drol утверждает, что Си++ в этом плане "отстой", а C# "рулит".
VE>>Показать ему, что это две стороны одной медали, мне не удалось. Он перешёл на хамство и мы закончили диалог.

G>
VE>>file f1, f2, f3;
VE>>foo();
VE>>bar();
VE>>f1.close(); f2.close(); f3.close();
VE>>
G>

G>В вашем коде, если деструктор file вызывает close, и в нем может вылетет exception, то программа вообще может аварийно завершиться.
G>Если деструктор не вызывает close, то фактически ресурс (файл) окажется незакрытым.

Я в C++ном коде, если функции освобождения ресурсов выбрасывали исключения, применял такой подход: вызывал их в деструкторе обернутыми в try/catch. Т.е. исключения в деструкторе проглатывались.

При таком подходе пример VoidEx-а будет нормально работать и незакрытых ресурсов не будет оставаться.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[31]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 11.08.08 10:18
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Ну а где гарантии что в реальной программе такого не произойдет? Никаких — значит нафиг.


Идите и расскажите это Страуструпу

D>>Если в Вашем примере оставить только один объект — всё будет нормально. То бишь "недодеструкченный" объект + продолжающая работать как ни в чём не бывало программа.

CC>Т.е. в тепличных условиях может и будет работать.

Повторяю ещё раз: с точки зрения стандарта C++ "недодеструкченность" допустима. И значит не является источником проблемы terminate()

Так что жду свежих предложений...
Re[42]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 11.08.08 10:28
Оценка:
Здравствуйте, eao197, Вы писали:

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


VE>>>Ничем не хуже. Но в этом коде вылетит то исключение, которое будет выброшено последним. В коде Си++ то, которое вылетело первым (так как деструкторы уже не бросят).

VE>>>drol утверждает, что Си++ в этом плане "отстой", а C# "рулит".
VE>>>Показать ему, что это две стороны одной медали, мне не удалось. Он перешёл на хамство и мы закончили диалог.

G>>
VE>>>file f1, f2, f3;
VE>>>foo();
VE>>>bar();
VE>>>f1.close(); f2.close(); f3.close();
VE>>>
G>>

G>>В вашем коде, если деструктор file вызывает close, и в нем может вылетет exception, то программа вообще может аварийно завершиться.
G>>Если деструктор не вызывает close, то фактически ресурс (файл) окажется незакрытым.

E>Я в C++ном коде, если функции освобождения ресурсов выбрасывали исключения, применял такой подход: вызывал их в деструкторе обернутыми в try/catch. Т.е. исключения в деструкторе проглатывались.

Я, наверное, тоже так делал бы.

E>При таком подходе пример VoidEx-а будет нормально работать и незакрытых ресурсов не будет оставаться.

Тогда практически нет смысла использовать явные close.
Re[43]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 11.08.08 10:30
Оценка:
Здравствуйте, gandjustas, Вы писали:

E>>При таком подходе пример VoidEx-а будет нормально работать и незакрытых ресурсов не будет оставаться.

G>Тогда практически нет смысла использовать явные close.

Явный close -- наверное. А вот явный flush здесь бы был к месту.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[40]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 11.08.08 10:51
Оценка:
Здравствуйте, nikov, Вы писали:

G>>А каким образом UnhandledException узнает о двух исключениях?


N>Он вызывается два раза.


Но как? Чтобы понять что нужно вызвать UnhandledException нужно раскрутить стек и вызвать все finally. Или нет?

В качестве доп.инфы: в Smalltalk (и вероятно в других языках с продолжаемыми исключениями) при вызове исключения просто происходит поиск обработчика без раскрутки стека. Раскрутка стека (и вызов finally) происходит потом, если исключение не рестартовано. Т.е. два метода:
main
    [ self except ] 
        on: Error 
        do: [:ex | Transcript show: 'handled'; cr]
        
except
    [ Error raiseSignal ]
        ensure: [Transcript show: 'finally'; cr]


Если вызвать "main", то будет напечатано

handled
finally

А если в блоке ensure: (типа "finally") выбросить исключение, то оно уйдёт на верх и finally в низу будет вызван уже после обработки этого нового исключения. Т.е. получится:

handled
<<Unhandled exception>>
finally

http://www.smalltalk.ru << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[43]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: VoidEx  
Дата: 11.08.08 11:11
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Тогда практически нет смысла использовать явные close.


Здесь сетовали на то, что исключения из деструктора не кинуть, потому если всё пройдёт гладко, а ошибка будет в дектрукторе, — никто об этом не узнает.
Вместо close может быть commit, flush, что угодно, в зависимости от класса. При таком подходе если всё пройдёт гладко, то вызовется явный flush и выбросится исключение, если исключение вылетит раньше, то отработает "тихий" деструктор, а пользователь поймает исходное исключение.
Re[41]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: nikov США http://www.linkedin.com/in/nikov
Дата: 11.08.08 11:40
Оценка: 8 (2)
Здравствуйте, Andrei N.Sobchuck, Вы писали:

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


G>>>А каким образом UnhandledException узнает о двух исключениях?


N>>Он вызывается два раза.


ANS>Но как? Чтобы понять что нужно вызвать UnhandledException нужно раскрутить стек и вызвать все finally. Или нет?


В процессе поиска подходящего блока catch блоки finally не выполняются. Они выполняются:
1) после того, как блок catch был найден и до того, как он был выполнен
2) или (если блок catch не был найден) после того, как выполнился обработчик UnhandledException
Re[42]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 11.08.08 11:54
Оценка:
Здравствуйте, nikov, Вы писали:

N>В процессе поиска подходящего блока catch блоки finally не выполняются. Они выполняются:

N>1) после того, как блок catch был найден и до того, как он был выполнен
N>2) или (если блок catch не был найден) после того, как выполнился обработчик UnhandledException

Во прикол. А есть обоснование такому поведению или "оно само так получилось"?
http://www.smalltalk.ru << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[36]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: CreatorCray  
Дата: 11.08.08 12:59
Оценка: +1 -1
Здравствуйте, VoidEx, Вы писали:

VE>Извините, но продолжать с вами разговор я больше не хочу.

VE>Упирайтесь рогом перед зеркалом и хамите туда же.
Не корми больше этого тролля.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[32]: Оффтоп
От: Кэр  
Дата: 11.08.08 14:59
Оценка:
Ник, хорош детей учить программировать Засылай лучше мне CV на мыло, я его передам куда надо. Мы тут Google борем, прикольно учавствовать
Re[29]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 12.08.08 12:49
Оценка:
Здравствуйте, eao197, Вы писали:

E>При раскрутке стека начнут вызываться деструкторы для 10K объектов B. Каждый из них выбрасывает свое исключение. Куда их все помещать? А что делать, если при их сохранении заканчивается свободная память?


Ну а что делают, когда, например, стек заканчивается ? Здесь то же самое: сами себе злые буратины писать такой код...

D>>Пойматься же должно в первом catch'е подходящем под какое-нибудь из цепочки.

E>Допустим, что при раскрутке стека все исключения удалось сохранить и есть множество исключений, состоящее из одного исключения another_exception_t и 10K исключений some_exception_t. Для какого из экземпляров some_exception_t должен сработать catch в d()?

Для первого выброшенного этого типа.

E>Что делать с остальными экземплярами?


К ним должен быть обеспечен доступ из catch'а.
Re[30]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 12.08.08 13:36
Оценка:
Здравствуйте, drol, Вы писали:

E>>При раскрутке стека начнут вызываться деструкторы для 10K объектов B. Каждый из них выбрасывает свое исключение. Куда их все помещать? А что делать, если при их сохранении заканчивается свободная память?


D>Ну а что делают, когда, например, стек заканчивается ? Здесь то же самое: сами себе злые буратины писать такой код...


А к коду-то какие претензии? Мы же рассматриваем случай, когда из деструкторов можно бросать исключения. Вот они и бросаются -- почему же сразу "такой код"?

D>>>Пойматься же должно в первом catch'е подходящем под какое-нибудь из цепочки.

E>>Допустим, что при раскрутке стека все исключения удалось сохранить и есть множество исключений, состоящее из одного исключения another_exception_t и 10K исключений some_exception_t. Для какого из экземпляров some_exception_t должен сработать catch в d()?

D>Для первого выброшенного этого типа.


А чем первое лучше любого другого? В частности, последнего?

E>>Что делать с остальными экземплярами?


D>К ним должен быть обеспечен доступ из catch'а.


Интересно, в каком языке программирования есть подобные catch-и?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[30]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 12.08.08 13:38
Оценка:
Здравствуйте, drol, Вы писали:

D>>>Пойматься же должно в первом catch'е подходящем под какое-нибудь из цепочки.

E>>Допустим, что при раскрутке стека все исключения удалось сохранить и есть множество исключений, состоящее из одного исключения another_exception_t и 10K исключений some_exception_t. Для какого из экземпляров some_exception_t должен сработать catch в d()?

D>Для первого выброшенного этого типа.


Ну допустим. Тогда следующий вопрос: пусть в d() catch выполняет нормальную обработку и восстановление после исключения some_exception_t (т.е. из catch ничего не выбрасывается). Что тогда делать с another_exception_t, которое так же было в исходном множестве исключений?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[31]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Adriano  
Дата: 12.08.08 14:57
Оценка:
Здравствуйте, eao197, Вы писали:

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


D>>>>Пойматься же должно в первом catch'е подходящем под какое-нибудь из цепочки.

E>>>Допустим, что при раскрутке стека все исключения удалось сохранить и есть множество исключений, состоящее из одного исключения another_exception_t и 10K исключений some_exception_t. Для какого из экземпляров some_exception_t должен сработать catch в d()?

D>>Для первого выброшенного этого типа.


E>Ну допустим. Тогда следующий вопрос: пусть в d() catch выполняет нормальную обработку и восстановление после исключения some_exception_t (т.е. из catch ничего не выбрасывается). Что тогда делать с another_exception_t, которое так же было в исходном множестве исключений?


мое ИМХО:
должен быть задокументирован список исключений, которые может бросать метод/функция и кроме них ничего не должно вылетать
разумно использовать исключения для критических ошибок, после которых не предполагается продолжение работы

зы
читал интервью, где программист из google рассказывал о их стиле программирования на с++ (ссылку не могу найти), так вот говорит, что в своих классах не используют исключения вообще, только коды возврата.
Re[32]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 12.08.08 15:17
Оценка:
Здравствуйте, Adriano, Вы писали:

A>мое ИМХО:

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

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

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


Зачем же тогда исключения? std::abort() и всех делов.

A>зы

A>читал интервью, где программист из google рассказывал о их стиле программирования на с++ (ссылку не могу найти), так вот говорит, что в своих классах не используют исключения вообще, только коды возврата.

У них официальный code style такой. Уже обсасывали эту тему на просторах форма "C++": здесь
Автор: night beast
Дата: 02.07.08


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[31]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 12.08.08 20:29
Оценка:
Здравствуйте, eao197, Вы писали:

E>А к коду-то какие претензии? Мы же рассматриваем случай, когда из деструкторов можно бросать исключения. Вот они и бросаются -- почему же сразу "такой код"?


Потому что 10К нетривиальных автоматических объектов за раз.

E>А чем первое лучше любого другого? В частности, последнего?


"Чем лучше ? Чем армяне" (с) народ

E>>>Что делать с остальными экземплярами?

D>>К ним должен быть обеспечен доступ из catch'а.
E>Интересно, в каком языке программирования есть подобные catch-и?

Не знаю. Языков ведь навалом...

Как похожую (в плане доступности кучи исключений) фичу в C# сделать, я уже показывал. Опять-таки InnerException ещё есть...
Re[31]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 12.08.08 20:41
Оценка:
Здравствуйте, eao197, Вы писали:

E>Ну допустим. Тогда следующий вопрос: пусть в d() catch выполняет нормальную обработку и восстановление после исключения some_exception_t (т.е. из catch ничего не выбрасывается). Что тогда делать с another_exception_t, которое так же было в исходном множестве исключений?


Ничего. catch ведь отработал => цирк уехал.

Логика примерно такая же, как в случае ловли исключения по базовому классу. Реально пойманный объект ведь может быть совсем другого типа, и даже многих других типов (приветствуем множественное наследование ), но catch рассматривает только контракт базового класса.

*Такими темпами я Вам скоро целый язык спроектирую
Re[32]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 13.08.08 06:49
Оценка:
Здравствуйте, drol, Вы писали:

E>>А к коду-то какие претензии? Мы же рассматриваем случай, когда из деструкторов можно бросать исключения. Вот они и бросаются -- почему же сразу "такой код"?


D>Потому что 10К нетривиальных автоматических объектов за раз.


Офигеть. 10K объектов -- это вообще ничто.

Более того, аналогия с переполнение стека не корректна. Переполнение стека можно cпрогнозировать. И можно с ним бороться увеличением стека при порождении новых нитей приложения. В любом случае ситуация с переполнением стека будет легко поторяться -- при тех же самых входнах данных программа должна вылетать из-за переполнения стека. А вот с исключениями в деструкторе, когда у системы не хватает памяти, чтобы собрать их воедино, может получиться трудновоспроизводимое поведение: иногда приложение будет падать при 10K исключений, иногда не будет, а иногда будет падать при 5K.

E>>А чем первое лучше любого другого? В частности, последнего?


D>"Чем лучше ? Чем армяне" (с) народ


Т.е. четкого обоснования не будет?
Почему я не удивлен?

E>>>>Что делать с остальными экземплярами?

D>>>К ним должен быть обеспечен доступ из catch'а.
E>>Интересно, в каком языке программирования есть подобные catch-и?

D>Не знаю. Языков ведь навалом...


D>Как похожую (в плане доступности кучи исключений) фичу в C# сделать, я уже показывал.


Мы же сейчас не о C# говорим. Но меня интересует другое. Наличие N экземпляров исключения одного типа означает, что catch должен выглядеть как-то так:
catch( const std::exception ** exceptions )
{
  for( const std::exception ** p = exceptions; *p; ++p )
    // Обработка очередного экземпляра исключения.
    ...
}


Это означает, что все catch-и в C++ должны были бы выглядеть именно так.

D>Опять-таки InnerException ещё есть...


В C++?
В С++ в качестве исключения можно выбросить все, что угодно, хоть std::exception, хоть int, хоть char*. Может покажете, как к int или char* привязать InnerException?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[32]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 13.08.08 06:56
Оценка:
Здравствуйте, drol, Вы писали:

E>>Ну допустим. Тогда следующий вопрос: пусть в d() catch выполняет нормальную обработку и восстановление после исключения some_exception_t (т.е. из catch ничего не выбрасывается). Что тогда делать с another_exception_t, которое так же было в исходном множестве исключений?


D>Ничего. catch ведь отработал => цирк уехал.


Вам самому не смешно?
Сначала в программе выбрасывается, например, исключение о том, что у текущего пользователя нет прав для проведения текущей операции. В процессе раскрутки стека выскакивает исключение о том, что коннект к БД был потерян (совпадение, допустим). Это исключение обрабатывается, а о нарушении прав доступа мы благополучно забываем -- ну не было его, совсем.

D>Логика примерно такая же, как в случае ловли исключения по базовому классу. Реально пойманный объект ведь может быть совсем другого типа, и даже многих других типов (приветствуем множественное наследование ), но catch рассматривает только контракт базового класса.


Интересная у вас логика. Только не правильная. Исключения по базовому классу ловятся для других целей.

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

D>*Такими темпами я Вам скоро целый язык спроектирую


Не льстите себе.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[33]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 14.08.08 07:29
Оценка:
Здравствуйте, eao197, Вы писали:

D>>Потому что 10К нетривиальных автоматических объектов за раз.

E>Офигеть. 10K объектов -- это вообще ничто.

Не в количестве вопрос, а в том что Вы делаете с этим количеством за одну операцию. Ну представьте 10К вложенных finally в коде на Java/C#...

E>Более того, аналогия с переполнение стека не корректна. Переполнение стека можно cпрогнозировать.


10К исключений тоже можно спрогнозировать.

E>И можно с ним бороться увеличением стека при порождении новых нитей приложения.


Ага-ага, особенно с рекурсиями неограниченной явно глубины...

E>А вот с исключениями в деструкторе, когда у системы не хватает памяти, чтобы собрать их воедино, может получиться трудновоспроизводимое поведение: иногда приложение будет падать при 10K исключений, иногда не будет, а иногда будет падать при 5K.


А если в деструкторе написать рандомный exit(0) всё будет ещё хуже.

E>>>А чем первое лучше любого другого? В частности, последнего?

D>>"Чем лучше ? Чем армяне" (с) народ
E>Т.е. четкого обоснования не будет?

Оно уже было указано в форме риторической цитаты

Перевод для слишком серьёзных читателей: разницы нет, так как мы всё равно собираемся предоставлять средства для доступа ко всей толпе исключений.

E>Это означает, что все catch-и в C++ должны были бы выглядеть именно так.


С каких это ??? catch'и должны выглядеть по-всякому. И, разумеется, нужна обычная форма, для случаев когда стада зависимых исключений не интересуют.

E>В С++ в качестве исключения можно выбросить все, что угодно, хоть std::exception, хоть int, хоть char*. Может покажете, как к int или char* привязать InnerException?


Мы же синтаксис в любом случае корёжим — всё возможно
Re[34]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 14.08.08 07:42
Оценка:
Здравствуйте, drol

Ну что тут сказать. Вы пытаетесь доказать, что C++ мог бы быть другим. Дык с этим никто и не спорит.

Вы пытаетесь доказать, что ваш подход с разрешением выпуска исключений из деструкторов с поимкой их всех и предоставлением к ним доступа из catch лучше и логичнее. Не получается. В вашем подходе не видно ни простоты, ни логичности.

Думаю, что тема исчерпана.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[12]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Danchik Украина  
Дата: 14.08.08 09:46
Оценка:
Здравствуйте, nikov, Вы писали:

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


D>>Что то я сомневаюсь что managed языки не используют подсчет ссылок для определения свободен ли обьект или нет для освобождения через GC. Есть другие мнения?


N>.NET не использует подсчет ссылок. Он строит граф достижимых объектов, остальные автоматически умирают при дефрагментации.


Это понятно. Только не понятно по какому принципу он его строит, где хранятся зависимости, они не требуют синхронизации?
Re[13]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: drol  
Дата: 14.08.08 17:08
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Это понятно. Только не понятно по какому принципу он его строит, где хранятся зависимости,


Ссылки внутри объектов известны из метаданных. Списки стековых корневых объектов тоже никаких снихронизаций не требуют, бо каждый в пределах своего потока. Статические корневые объекты также не представляют проблем. Что там ещё ? Очередь финализируемых ? Вроде тоже никаких особых граблей.

D>они не требуют синхронизации?


В данном случае только одна могучая синхронизация — остановка исполнения на время работы собственно GC
Re[14]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: WFrag США  
Дата: 15.08.08 05:13
Оценка:
Здравствуйте, drol, Вы писали:

D>В данном случае только одна могучая синхронизация — остановка исполнения на время работы собственно GC


Это не обязательно, есть разные алгоритмы GC, в том числе и те, которые не требуют остановку приложения на всё время работы GC (остановка требуется, но только на часть работ, основная работа выполняется конкурентно с приложением).
Re[13]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: Cyberax Марс  
Дата: 15.08.08 05:18
Оценка:
Здравствуйте, Danchik, Вы писали:

N>>.NET не использует подсчет ссылок. Он строит граф достижимых объектов, остальные автоматически умирают при дефрагментации.

D>Это понятно. Только не понятно по какому принципу он его строит, где хранятся зависимости, они не требуют синхронизации?
Зависимости нигде не хранятся, соответственно синхронизация не нужна. Строится по "простому" принципу — обходятся все достижимые объекты, начиная с корневых.

Естественно, используется куча сложных оптимизаций, типа системы поколений.
Sapienti sat!
Re[19]: Зачем нужен сборщик мусора? Как жить без деструкторо
От: vdimas Россия  
Дата: 26.08.08 16:14
Оценка:
Здравствуйте, eao197, Вы писали:

E>А что же будет, если выход из блока кода происходит по исключению? Какое исключение будет выпущено наружу -- которое из блока кода или из Dispose?


В С# такая проблема не стоит, т.к. все ислючения — это типы корнем от одного ссылочного типа Exception. Соответственно, подменить в текущем слоте стека один объект исключения на другой можно запросто. Более того, объекты исключений могут вкладываться друг в друга (последнее ссылается на предыдущее), образуя однонаправленный список, т.е. имея последний объект исключения, можно получить всю цепочку и докопаться до первопричины, будь такое желание.

Другое дело С++, где тип исключения произволен, к тому же может распространяться как по значению, так и по ссылке/указателю, и не придуман еще адекватный способ "подмены" ошибок или сохранения всей этой драмматической цепочки исключений (ИМХО, такого способа не существует принципиально в отсутствии GC).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.