На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
  
> Сравнение производительности Java и Delphi/C++
    Пусть чистый код привязан к операционке, зато более производителен, и я выбираю именно его. А жаба и дотнет гуляют лесом :whistle:
    По поводу сабжа - мне абсолютно без разницы (п.#4)... Пользую проги писанные и на том, и на том, если нет альтернативы. Сам на дотнете и жабе не пишу и не собираюсь.

    Эта тема была разделена из темы "Java vs .NET"; см. также тему "Сравнение производительности Delphi & C++"
      Цитата --= Eagle =-- @
      Пусть чистый код привязан к операционке, зато более производителен, и я выбираю именно его.

      Потестим?
        wind, напиши "Hello, world!" на дотнете и жабе, а я напишу на делфе. Посмотрим :yes:
          Цитата --= Eagle =-- @
          wind, напиши "Hello, world!" на дотнете и жабе, а я напишу на делфе.

          Упаси меня Бог когда-либо дотрагиваться до дотнета :lol: На java-то напишу, а как тестить будем? Нужен бы какой-то алгоритм, который будет реализован на delphi и java. Какие будут предложения?
            Цитата wind @
            Потестим?

            Ну так присоединяйся ;)
              Вот, набросал что-то. Надо заметить, благодаря наличию некоторых стандартных классов это было довольно просто ;)
              Файл .java - исходник, .class - бинарник. Для запуска установить jre 1.5 или выше, затем в командной строке из папки с Test.class:

              ExpandedWrap disabled
                java -cp . Test <src-file> <dst-file> [sort]
              Сообщение отредактировано: wind -

              Прикреплённый файлПрикреплённый файлTest.zip (3.21 Кбайт, скачиваний: 169)
                wind, будь так добр - скомпиль в бинарник, ага? ;)
                  Цитата --= Eagle =-- @
                  wind, будь так добр - скомпиль в бинарник, ага?

                  Дык о каком бинарнике речь? Оно скомпилировано и для запуска в jre готово. Или вы не хотите jre ставить?
                  Сообщение отредактировано: wind -
                    wind, а чё, без него никак? :unsure:
                      Опыт будет не показательным. Ибо время потраченное на старт виртуальной машины тож будет посчитано.

                      Добавлено
                      --= Eagle =--, никак. А ты проги написанные на джаве вообще не используешь? :ph34r:
                        Цитата --= Eagle =-- @
                        wind, а чё, без него никак?

                        --= Eagle =--, слазь с ветки - оно потому и платформенно-независимое, что есть прокладка в виде виртуальной машины :) А вот она-то как раз пишется под платформу, то есть портируется.
                          Цитата --= Eagle =-- @
                          wind, а чё, без него никак?

                          Я могу сотворить exe'шник, но jre придётся в него включить (~15 мб), так что если только вечером закачаете с моей домашней машины.

                          Цитата DUKe @
                          Опыт будет не показательным. Ибо время потраченное на старт виртуальной машины тож будет посчитано.

                          Это мы ещё обсудим :) В принципе, можно довериться измерению времени внутри программы (нужно только его реализовать в дельфовом примере), как сделал я. Нас ведь не интересуют незначительные расхождения?
                          Сообщение отредактировано: wind -
                            Цитата DUKe @
                            А ты проги написанные на джаве вообще не используешь?

                            Иногда... _очень_ редко. И мне почему-то казалось, что я таки видел скомпиленные бинарники...

                            Добавлено
                            Я уже скачал, проверил - работает...
                            Кроме того, лично меня всегда интересовала юзабельность и удобность работы с бинарником. В жабе это выглядит... кхм... не весьма лицеприятно :yes:
                              Цитата --= Eagle =-- @
                              И мне почему-то казалось, что я таки видел скомпиленные бинарники...

                              Скомпилить бинарник можно метод описанным wind'ом, но это ивращение.


                              Цитата wind @
                              Это мы ещё обсудим :)

                              а чего тут обсуждать-то?

                              Добавлено
                              --= Eagle =--, обычно все class файлы пакуются в *.jar, а как запускалка к нему пишется скрипт.

                              ЗЫ винду можно настроить, чтобы она из проводника по двойному щелчку запускала джарник.
                                DUKe, это я в курсе, просто не подозревал, что для того, чтобы скомпилить бинарник нужны такие жуткие извраты :wacko:
                                  Цитата DUKe @
                                  Скомпилить бинарник можно метод описанным wind'ом, но это ивращение.

                                  Неа :no: Я не имел в виду компиляцию jre, только exe для запуска и jre рядом.

                                  Цитата --= Eagle =-- @
                                  Кроме того, лично меня всегда интересовала юзабельность и удобность работы с бинарником.

                                  Можно делать только скрипт, можно делать бинарник (само собой, придётся делать под все платформы - в этом и засада). JRE при этом может быть упакована в сам бинарник, может лежать рядом и (это уже как раз извращение) может быть прикомпилирована в том же бинарнике.

                                  Кроссплатформенность ведь :)
                                  Сообщение отредактировано: wind -
                                    Цитата --= Eagle =-- @
                                    DUKe, это я в курсе, просто не подозревал, что для того, чтобы скомпилить бинарник нужны такие жуткие извраты :wacko:

                                    *.class это уже бинарник. Просто он платформонезависимый =)
                                      Цитата wind
                                      Я могу сотворить exe'шник, но jre придётся в него включить (~15 мб),

                                      15-метров.. да уж.. удивительно как в своё время Borland ухитрился консольный java-компиль Bcj.exe в ~2метра уложить, в JBuilder-e №3.. :huh: и нативного в ней мало больше половины
                                      Цитата bcj.exe

                                      [=L (Ljava/lang/Object;
                                      Ljava/lang/StringBuffer; forma
                                      text/FieldPosition;)Ljava/lang
                                      g/String; format (Ljava/lang/

                                      да уж умели раньше делать.. юзаю иногда.. уже пяток 'опенсурсовых' j2me игр.. собраных JAD->BCJ.. Кстати не вышло сейчас ни каких продвинутых деобфускаторов? Oper'у бы разобрать.. и собрать.. а то что это, jar-ки, бинарники... ерунда какая то в самом деле. :(

                                      Добавлено
                                      Цитата

                                      Borland Compiler 1.2.006 for Java
                                      Copyright © 1997-1999 Inprise Corporation. All Rights Reserved.

                                      вещь.. и рунтайма не требует, никакого :)
                                        Цитата n0p @
                                        удивительно как в своё время Borland ухитрился консольный java-компиль Bcj.exe в ~2метра уложить

                                        Не факт, что bcj написан на java. А строки в бинарнике - куда же без этого, это сигнатуры типов. А если предположить, что на java, то стоит попробовать запустить, удалив все jre и jdk из системы ;)
                                        Сообщение отредактировано: wind -
                                          на джаве он писан! как и bcj от JBuilder7.. (v 1.3) тока последний просил Sun Jre. а ексешка была маленькая, калбачила в hotswap jvm.dll.. все основное было в здоровенной jar-ke. помниться я даже выуживал его оттуда.. делал маленький.. гдето на метр.. но что то он мне не порулил - уж больно инертно прогружался, и компилил. все таки раньше -были в теме.. даже goto был в борландовском, а суновский возмущался.. :huh:

                                          Добавлено
                                          Цитата wind
                                          А если предположить, что на java, то стоит попробовать запустить, удалив все jre и jdk из системы

                                          так маленький jvm был в нем, а больше половины - классы Java-runtaim-а и собственно компилятора.. ;)
                                            Цитата DUKe @
                                            А ты проги написанные на джаве вообще не используешь? :ph34r:

                                            Я — нет ;)

                                            Добавлено
                                            И как же мне его побенчмаркить?

                                            wind, а у тебя-то он какое время выдал? Сопоставимое с тем, что в моих бенчмарках?
                                              Цитата Smike @
                                              И как же мне его побенчмаркить?

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

                                              А можно мерялку внутрь встроить
                                                Цитата Smike @
                                                Сопоставимое с тем, что в моих бенчмарках?

                                                Я пока других вариантов не смотрел, у меня работает за 7 млн. наносекунд. Мерялка внутри.
                                                  А, у тебя же нет файлов для тестирования, которые я использовал. На какого размера файле тестируешь хоть?
                                                    Цитата Smike @
                                                    А, у тебя же нет файлов для тестирования, которые я использовал. На какого размера файле тестируешь хоть?

                                                    На ма-а-аленьком файлике в двадцать строк. А где мне взять ваши файлы? Или какой объём порекомендуете для теста?
                                                      Вот файлы, на которых я тестировал: http://rapidshare.com/files/29320243/Test.rar
                                                        Цитата Smike @
                                                        Вот файлы, на которых я тестировал: http://rapidshare.com/files/29320243/Test.rar

                                                        На Input3.txt я получил 19 сек. (усред. по трём запускам - 21, 18, 18) без сортировки и 23 сек. (23, 24, 23) с сортировкой. Надо заметить, у меня ещё довольно халтурная реализация - всё что мог, я переложил на стандартные классы.

                                                        ExpandedWrap disabled
                                                          C:\Temporary>java -Xmx512m -classpath . Sample Input3.txt dst.txt
                                                          Elapsed time: 21348985252 nanoseconds
                                                           
                                                          C:\Temporary>java -Xmx512m -classpath . Sample Input3.txt dst.txt sort
                                                          Elapsed time: 23711151514 nanoseconds
                                                           
                                                          C:\Temporary>java -Xmx512m -classpath . Sample Input3.txt dst.txt
                                                          Elapsed time: 18355008011 nanoseconds
                                                           
                                                          C:\Temporary>java -Xmx512m -classpath . Sample Input3.txt dst.txt sort
                                                          Elapsed time: 24057192980 nanoseconds
                                                           
                                                          C:\Temporary>java -Xmx512m -classpath . Sample Input3.txt dst.txt
                                                          Elapsed time: 18308329811 nanoseconds
                                                           
                                                          C:\Temporary\333>java -Xmx512m -classpath . Sample Input3.txt dst.txt sort
                                                          Elapsed time: 23743929350 nanoseconds
                                                        Сообщение отредактировано: wind -
                                                          Ну а вот что получилось у нас:
                                                          http://smike.drkb.ru/temp/StringTestResults.htm
                                                            Цитата Smike @
                                                            Ну а вот что получилось у нас:
                                                            http://smike.drkb.ru/temp/StringTestResults.htm

                                                            Не открывается :(
                                                              Цитата wind @
                                                              Не открывается :no:

                                                              Весьма странно, думаю проблема у твоего провайдера.

                                                              Ну тогда вот
                                                              Скрытый текст
                                                              (не подумайте, что пиарю Сисман, просто больше некуда HTML выложить)
                                                                Ну что же, мне результаты уже нравятся. Быстрейший из примеров обгоняет всего лишь в 2,5 раза (не говоря уж о значительном отрыве от тормознейшего из). Если в моём примере выкинуть всё лишнее (навроде регэкспа), думаю, результаты будут значительно лучше.

                                                                Добавлено

                                                                Хотя, имеет значение на какой машинке всё это отработало. Попробую у себя запустить все ваши тесты.
                                                                Сообщение отредактировано: wind -
                                                                  Smike, а чем вы замеряли время выполнения?
                                                                    Цитата wind @
                                                                    Smike, а чем вы замеряли время выполнения?

                                                                    CreateProcess + GetProcessTimes
                                                                      Я забыл дома модифицированный пример, из которого выкинул регэксп - заработало почти вдвое быстрее. Вечером постараюсь выложить результаты. Примечательно, что с сортировкой работает дольше, видимо проседает на многочисленных операциях new при добавлении в дерево. Также примечательно, что из всего времени работы ~90% съедает разбиение строки на категорию/подкатегорию/элемент; возможно, если не использовать стандартный класс String, работать будет быстрее (но это уже извращение).
                                                                        Вот и результаты. Довольно интересные, если сравнивать с тестами Smike.
                                                                        Время в миллисекундах.

                                                                        +------------------+--------------+---------------------+------------+-------------------+
                                                                        |                  | Input3sm.txt | Input3sm.txt + sort | Input3.txt | Input3.txt + sort |
                                                                        +------------------+--------------+---------------------+------------+-------------------+
                                                                        | myaut_tree.exe   |         1531 |                2750 |       8390 |             13532 |
                                                                        +------------------+--------------+---------------------+------------+-------------------+
                                                                        | StringsToMap.exe |         2015 |                2000 |      10297 |             10063 |
                                                                        +------------------+--------------+---------------------+------------+-------------------+
                                                                        | Tree2.exe        |         1656 |                2343 |       8547 |             11828 |
                                                                        +------------------+--------------+---------------------+------------+-------------------+
                                                                        | java ReadToMap   |         2578 |                3360 |      10986 |             15672 |
                                                                        +------------------+--------------+---------------------+------------+-------------------+
                                                                        

                                                                        Мой обновлённый пример прикреплён. Пример Мяута вообще какой-то очень хитрый. Возвращает управление молниеносно, а затем в течение 5-6 секунд пухнет результирующий файл :huh:

                                                                        З. Ы. Как видите, нет результатов примера archimedа. Если кто-нить мне его скомпилирует, я не обижусь :)

                                                                        З. З. Ы. Результаты подправил - мой пример валился ближе к концу файла с ошибкой (обнаружилось при сличении результирующих файлов :)).

                                                                        З. З. З. Ы. С примером Мяута тоже разобрался - сделал свою запускалку - теперь результаты похожи на правду.

                                                                        З. З. З. З. Ы. И еще раз подправил результаты - закрыл всё лишнее и запустил все варианты в одном скрипте.
                                                                        Сообщение отредактировано: wind -

                                                                        Прикреплённый файлПрикреплённый файлReadToMap.zip (3.21 Кбайт, скачиваний: 112)
                                                                          Цитата
                                                                          Пример Мяута вообще какой-то очень хитрый. Возвращает управление молниеносно, а затем в течение 5-6 секунд пухнет результирующий файл
                                                                          =)))))))Блин, а заинтриговало)))) Мяут - ану колись что/как намутил? ^_^
                                                                            Цитата wind @
                                                                            Возвращает управление молниеносно, а затем в течение 5-6 секунд пухнет результирующий файл :huh:

                                                                            Цитата AngelPS @
                                                                            =)))))))Блин, а заинтриговало)))) Мяут - ану колись что/как намутил? ^_^

                                                                            Видимо это все из-за несовершенства способа измерения ;)
                                                                              я поставил опцию "без создания консольного окна". а наф мне консольное окно? =)

                                                                              Добавлено
                                                                              wind, интересно, какой ты брал пример и сравнивал ли ты файлы с "эталоном" ;) Ибо 1я и 3я программа не очень-то корректно работают ;)

                                                                              Добавлено
                                                                              Цитата AngelPS @
                                                                              =)))))))Блин, а заинтриговало)))) Мяут - ану колись что/как намутил? ^_^

                                                                              Как вариант - я пишу слишком быстро и Windows просто буферизует мои данные для записи на жесткий диск. в итоге программа завершает свою работу до того как все данные будут слиты на жесткий диск. Ох уж эта многопоточность :rolleyes:
                                                                                Цитата Мяут @
                                                                                Как вариант - я пишу слишком быстро и Windows просто буферизует мои данные для записи на жесткий диск. в итоге программа завершает свою работу до того как все данные будут слиты на жесткий диск.

                                                                                Удачная шутка.

                                                                                Файлы закрываются при закрытии программы, стандартные операции записи не являются асинхронными.
                                                                                  Цитата Smike @
                                                                                  Удачная шутка.

                                                                                  Есть объяснение получше? =)

                                                                                  Добавлено
                                                                                  Цитата Smike @
                                                                                  стандартные операции записи не являются асинхронными.

                                                                                  ну то что я (верней моя программа) инициировала запись на диск вовсе не означает что эти данные сейчас же пойдут на диск. Они будет переданы драйверу диска, а тот уже распределит задачи на запись (их может быть несколько). А чтобы не потерять данные в очереди, он их буферизует =)) Я сейчас Таннебацма изучаю, так что... ;)
                                                                                    Цитата Мяут @
                                                                                    Есть объяснение получше? =)

                                                                                    Читай выше:
                                                                                    Цитата Smike @
                                                                                    Видимо это все из-за несовершенства способа измерения ;)


                                                                                    Так и быть, думаю выложу свою программу для бенчмарка. Только приведу её в нормальный вид сначала.
                                                                                    Цитата Мяут @
                                                                                    ну то что я (верней моя программа) инициировала запись на диск вовсе не означает что эти данные сейчас же пойдут на диск

                                                                                    Не путай Windows и Linux. В Windows есть кеш, но буфера диска нет.
                                                                                      Цитата Smike @
                                                                                      В Windows есть кеш, но буфера диска нет.

                                                                                      Буфер есть везде. Причем не только у диска. Если бы данные в windows не буферизовались, то все было бы очень медленно, так как операции должны были бы быть полностью синхронными.
                                                                                        Цитата Мяут @
                                                                                        А чтобы не потерять данные в очереди, он их буферизует =))

                                                                                        драйвер?! ОМГ! :blink:
                                                                                          Цитата Smike @
                                                                                          Видимо это все из-за несовершенства способа измерения

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

                                                                                          Цитата Мяут @
                                                                                          Есть объяснение получше?

                                                                                          Как раз из-за неиспользования консоли. Кстати, это нарушение правил ;)

                                                                                          Цитата Мяут @
                                                                                          wind, интересно, какой ты брал пример и сравнивал ли ты файлы с "эталоном"

                                                                                          А есть эталон? Все программы при включённой сортировке создали идентичные файлы. А у Мяута, кстати, при отключённой сортировке получается не такой размер, как у всех :tong:

                                                                                          Брал последнюю в той теме версию. А какую надо было?
                                                                                          Сообщение отредактировано: wind -
                                                                                            Цитата wind @
                                                                                            Брал последнюю в той теме версию. А какую надо было?

                                                                                            2ю. =)) 3ю нада отладить :)
                                                                                              Перемерял (со вторым вариантом Мяута); время в миллисекундах:

                                                                                              +------------------+--------------+---------------------+------------+-------------------+
                                                                                              |                  | Input3sm.txt | Input3sm.txt + sort | Input3.txt | Input3.txt + sort |
                                                                                              +------------------+--------------+---------------------+------------+-------------------+
                                                                                              | myaut_tree.exe   |         2219 |                2719 |      18079 |             12610 |
                                                                                              +------------------+--------------+---------------------+------------+-------------------+
                                                                                              | StringsToMap.exe |         1796 |                1875 |      10109 |              9390 |
                                                                                              +------------------+--------------+---------------------+------------+-------------------+
                                                                                              | Tree2.exe        |         1578 |                2281 |       8297 |             11281 |
                                                                                              +------------------+--------------+---------------------+------------+-------------------+
                                                                                              | java ReadToMap   |         2469 |                3157 |      10766 |             14844 |
                                                                                              +------------------+--------------+---------------------+------------+-------------------+
                                                                                              
                                                                                                wind, а ты чем меряешь?
                                                                                                  Цитата Smike @
                                                                                                  wind, а ты чем меряешь?

                                                                                                  Вот таким вот простеньким пускачом на java:

                                                                                                  ExpandedWrap disabled
                                                                                                    public class Runner {
                                                                                                        
                                                                                                        static String argsToString(Object[] array) {
                                                                                                            StringBuilder stringBuilder = new StringBuilder();
                                                                                                            
                                                                                                            for (Object element : array) {
                                                                                                                if (stringBuilder.length() > 0) {
                                                                                                                    stringBuilder.append(" ");
                                                                                                                }
                                                                                                                
                                                                                                                stringBuilder.append(element);
                                                                                                            }
                                                                                                            
                                                                                                            return stringBuilder.toString();
                                                                                                        }
                                                                                                     
                                                                                                        public static void main(String... args) throws IOException, InterruptedException {
                                                                                                            if (args.length < 1) {
                                                                                                                System.out.printf("Usage: Runner <command-line>\n");
                                                                                                                return;
                                                                                                            }
                                                                                                            
                                                                                                            ProcessBuilder processBuilder = new ProcessBuilder(args);
                                                                                                            System.out.printf("Running [%s]\n", argsToString(args));
                                                                                                            
                                                                                                            long start = System.currentTimeMillis();
                                                                                                            
                                                                                                            try {
                                                                                                                Process process = processBuilder.start();
                                                                                                                process.waitFor();
                                                                                                            }
                                                                                                            finally {
                                                                                                                System.out.printf("Process time: %s milliseconds\n\n", System.currentTimeMillis() - start);
                                                                                                            }
                                                                                                        }
                                                                                                        
                                                                                                    }


                                                                                                  Последовательно вызываю его с нужными аргументами в скрипте, записываю результаты второго запуска (чтобы как-то учесть кэширование осью).
                                                                                                    Цитата wind @
                                                                                                    Последовательно вызываю его с нужными аргументами в скрипте, записываю результаты второго запуска (чтобы как-то учесть кэширование осью).

                                                                                                    Как я и предполагал, бенчмарк не точен, так как учитывает время только от запуска до завершения. Я же пользовался точным временем работы процесса, возвращаемым Windows, а оно не зависит от внешних факторов.
                                                                                                      Цитата Smike @
                                                                                                      Как я и предполагал, бенчмарк не точен, так как учитывает время только от запуска до завершения. Я же пользовался точным временем работы процесса, возвращаемым Windows, а оно не зависит от внешних факторов.

                                                                                                      Имеется в виду время, потраченное на процесс процессором?

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

                                                                                                      З. Ы. Smike, выкладывайте ваш темпометр :)
                                                                                                      Сообщение отредактировано: wind -
                                                                                                        wind, а с какими параметрами запускается JVM? client mode или server mode? Какие размеры heap-а?
                                                                                                        Думаю, если с этими параметрами поиграться, результаты могут поменяться :unsure:
                                                                                                          Цитата tserega @
                                                                                                          wind, а с какими параметрами запускается JVM? client mode или server mode? Какие размеры heap-а?
                                                                                                          Думаю, если с этими параметрами поиграться, результаты могут поменяться :unsure:

                                                                                                          Heap предельный для обеспечения невмешательства GC; client mode.

                                                                                                          Можно было бы еще отказаться от использования java.lang.String, считывать весь файл целиком одним заходом, использовать собственные, более производительные реализации контейнеров вместо java.util.HashMap и java.util.TreeMap, учитывать неизменность данных - это могло бы дать существенный прирост производительности. Но я думаю, нет смысла оптимизировать пример, т. к. это уже снова станет похоже на синтетический тест, а этого я хотел бы избежать ;)
                                                                                                          Сообщение отредактировано: wind -
                                                                                                            Что же молчит --= Eagle =--? :whistle:

                                                                                                            Добавлено

                                                                                                            --= Eagle =--, АУ! Ради вас, можно сказать затеяли это тестирование, а вы не отзываетесь... :huh:
                                                                                                            Сообщение отредактировано: wind -
                                                                                                              а успевал ли отработать GC в яве? :)
                                                                                                                Цитата MAxZ @
                                                                                                                а успевал ли отработать GC в яве?

                                                                                                                Нет.
                                                                                                                  wind, ну дык тест получается некорректный?
                                                                                                                  я за яву, но истина интересней ;)
                                                                                                                    Цитата MAxZ @
                                                                                                                    wind, ну дык тест получается некорректный?

                                                                                                                    С чего это вдруг? Ни один из примеров не стесняет свои потребности в памяти. Кроме того, исчерпание выделенной памяти в java (и как следствие, запуск сборщика мусора по полной программе) есть признак кривой архитектуры приложения. Этого не должно происходить ни при каких обстоятельствах.
                                                                                                                      Цитата wind @
                                                                                                                      Кроме того, исчерпание выделенной памяти в java (и как следствие, запуск сборщика мусора по полной программе) есть признак кривой архитектуры приложения. Этого не должно происходить ни при каких обстоятельствах.

                                                                                                                      т.е.?
                                                                                                                      память выделяется?
                                                                                                                      очищать её нужно?
                                                                                                                        Цитата MAxZ @
                                                                                                                        очищать её нужно?

                                                                                                                        Нужно не доводить до дефицита памяти. Программа должна жить в отведённом ей объёме.
                                                                                                                        Сборщик мусора работает всегда, но когда памяти не хватает, работает непрерывно - это не нормальная ситуация.
                                                                                                                          Цитата wind @
                                                                                                                          Нужно не доводить до дефицита памяти. Программа должна жить в отведённом ей объёме.

                                                                                                                          а если программа работает 24 часа в сутки постоянно делая то что сделал тест 1 раз?
                                                                                                                            Цитата wind @
                                                                                                                            Цитата MAxZ @
                                                                                                                            wind, ну дык тест получается некорректный?

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

                                                                                                                            Предположим, что у меня есть компьютер - 1 штука. На нем комфортно крутятся 5-6 приложений. Теперь представим, что одно из этих приложений написанно на java. Если java приложение подомнет под себя много памяти и не будет ее долго возвращать, то ОС не сможет эффективно распределять доcтупную память между всеми приложениями.
                                                                                                                            Вывод: для Java противопоказаны многозадачные системы.
                                                                                                                              Цитата MAxZ @
                                                                                                                              а если программа работает 24 часа в сутки постоянно делая то что сделал тест 1 раз?

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

                                                                                                                              Цитата Alex Forth @
                                                                                                                              Предположим, что у меня есть компьютер - 1 штука. На нем комфортно крутятся 5-6 приложений. Теперь представим, что одно из этих приложений написанно на java. Если java приложение подомнет под себя много памяти и не будет ее долго возвращать, то ОС не сможет эффективно распределять доcтупную память между всеми приложениями.
                                                                                                                              Вывод: для Java противопоказаны многозадачные системы.

                                                                                                                              Чепуха. Java подомнёт под себя ровно столько памяти, сколько ей будет позволено подмять. Если же jvm работает в клиентском режиме, то лишняя память будет отдаваться системе.
                                                                                                                                Цитата wind @
                                                                                                                                Если же jvm работает в клиентском режиме, то лишняя память будет отдаваться системе.

                                                                                                                                Пример: программа обработки изображений. Пусть мне надо обработать большую фотку. Java-программа засасывает jpg файлик, раскручивает его в памяти в огромный битмап, производит все нужные действия, сохраняет результат. Несмотря на то, что после всех описанных действий битмап уже не нужен, он фактически будет лежать мертвым грузом в памяти java-машины, пока его от туда не выкинет gc. Следовательно какой-то опромежуток времени (GC его знает на сколько большой) GC не будет возвращать в ОС довольно большей кусок памяти, который java программе уже нафиг не нужен.
                                                                                                                                Не правда ли оптимальное использование памяти? ;)
                                                                                                                                  Цитата Alex Forth @
                                                                                                                                  Не правда ли оптимальное использование памяти?

                                                                                                                                  Описанное вами поведение можно ожидать только при запуске jvm в серверном режиме (я это уже говорил, вроде как). Сбор мусора происходит постоянно, для этого есть разные типы сборщиков. И если изображение больше не нужно, jvm в клиентском режиме отдаст всю лишню память системе.
                                                                                                                                  Сообщение отредактировано: wind -
                                                                                                                                    Неужели в яве такой тупой сборщик мусора? Взять те же дельфийские интерфейсы: они автоматически удаляются из памяти, когда перестают быть нужны. А в джаве все лежит мертвым грузом даже когда оно уже давно не нужно?
                                                                                                                                      Цитата Smike @
                                                                                                                                      А в джаве все лежит мертвым грузом даже когда оно уже давно не нужно?

                                                                                                                                      Нет.
                                                                                                                                        Цитата wind @
                                                                                                                                        И если изображение больше не нужно, jvm в клиентском режиме отдаст всю лишню память системе.

                                                                                                                                        И на сколько быстро отдаст?
                                                                                                                                          Цитата Alex Forth @
                                                                                                                                          И на сколько быстро отдаст?

                                                                                                                                          В тот же момент, когда на объект не останется ссылок.
                                                                                                                                            Цитата wind @
                                                                                                                                            В тот же момент, когда на объект не останется ссылок.

                                                                                                                                            А каковы при этом будут затраты CPU на поток GC, если у меня паралельно будет очень много маленьких взаимосвязанных обьектов?
                                                                                                                                              Цитата Alex Forth @
                                                                                                                                              А каковы при этом будут затраты CPU на поток GC, если у меня паралельно будет очень много маленьких взаимосвязанных обьектов?

                                                                                                                                              Не замерял. Могу только сказать, что затраты невелики, так как ни разу не встречал проблем с производительностью из-за работы сборщика (иными словами, на глаз - вообще затрат нет). Только если память заканчивается совсем, сборка идёт чуть ли не непрерывно и отъедает почти всё процессорное время (java не занимает всю доступную память, максимум задаётся при старте jvm). Но это бывает вызвано только ошибками в логике программы.

                                                                                                                                              Хотя, конечно же, фоновая сборка мусора какое-то время отнимает, не зря же cделана jvm реального времени.
                                                                                                                                                Цитата Alex Forth @
                                                                                                                                                А каковы при этом будут затраты CPU на поток GC, если у меня паралельно будет очень много маленьких взаимосвязанных обьектов?

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

                                                                                                                                                Только как определить выход из зоны видимости каких-то глобальных классов? В джаве вообще чтоли нету деструктора?
                                                                                                                                                  Цитата Smike @
                                                                                                                                                  В джаве вообще чтоли нету деструктора?

                                                                                                                                                  :no:

                                                                                                                                                  Если вы имеете в виду статические ссылки, то доступные по ним объекты не будут собраны, пока эти ссылки не обнулят явно. Иное было бы странно. Или вы что-то иное имеете в виду?
                                                                                                                                                    Wind, а GC клиентского режима в 1,5 появился или раньше?
                                                                                                                                                    Smike, ты забыл про циклические ссылки, там алгоритмы сбора мусора далеко не тривиальны :)
                                                                                                                                                    Сообщение отредактировано: Alex Forth -
                                                                                                                                                      Цитата Alex Forth @
                                                                                                                                                      Wind, а GC клиентского режима в 1,5 появился или раньше?

                                                                                                                                                      Описанное мною поведение я наблюдаю с java 1.4.0 (с более ранними версиями в клиентском режиме не сталкивался).

                                                                                                                                                      Цитата Alex Forth @
                                                                                                                                                      Smike, ты забыл про циклические ссылки, там алгоритмы сбора мусора далеко не тривиальны :)

                                                                                                                                                      Само собой. Как правило именно запутанные циклические ссылки приводят к захламлению всей доступной памяти. Грубо говоря, отсутствие каких-либо забот о распределении памяти в java - это миф, неиспользуемые ссылки всё равно стоит обнулять руками.
                                                                                                                                                      Сообщение отредактировано: wind -
                                                                                                                                                        Цитата wind @
                                                                                                                                                        Грубо говоря, отсутствие каких-либо забот о распределении памяти в java - это миф, неиспользуемые ссылки всё равно стоит обнулять руками.

                                                                                                                                                        Ага, и утечку памяти можно организовать!
                                                                                                                                                        Только зачем тогда такая жесткая привязка языка к GC ? :blink:
                                                                                                                                                          Цитата Alex Forth @
                                                                                                                                                          Только зачем тогда такая жесткая привязка языка к GC ?

                                                                                                                                                          Привязка?
                                                                                                                                                            Цитата wind @
                                                                                                                                                            Привязка?

                                                                                                                                                            выделение/освобождение памяти реализовывается только средствами java-машины. Использование внешнего менеджера памяти с явным выделением/освобождением невозможно. Или в последнем я не прав?
                                                                                                                                                              Цитата Alex Forth @
                                                                                                                                                              Использование внешнего менеджера памяти с явным выделением/освобождением невозможно. Или в последнем я не прав?

                                                                                                                                                              Правы насчёт явного управления памятью. Только при чём тут привязка к GC? Сборщики можно подключать, отключать, конфигурировать.
                                                                                                                                                                Цитата wind @
                                                                                                                                                                Только при чём тут привязка к GC? Сборщики можно подключать, отключать, конфигурировать.

                                                                                                                                                                Я в курсе, но свобода выбора способом управления памятью таки ограничена.
                                                                                                                                                                  Цитата Alex Forth @
                                                                                                                                                                  Я в курсе, но свобода выбора способом управления памятью таки ограничена.

                                                                                                                                                                  Свобода выбора всегда остаётся. Кому нужно "ручное" управление - пишут на C++.
                                                                                                                                                                    Цитата wind @
                                                                                                                                                                    Свобода выбора всегда остаётся. Кому нужно "ручное" управление - пишут на C++

                                                                                                                                                                    Ну если так, то свобода еще есть :)
                                                                                                                                                                    Только зачем было заморачиваться с GC, если все равно приходится держать в голове кучу особенностей по времени жизни обьектов?
                                                                                                                                                                      Цитата Alex Forth @
                                                                                                                                                                      Только зачем было заморачиваться с GC, если все равно приходится держать в голове кучу особенностей по времени жизни обьектов?

                                                                                                                                                                      Потому что в худшем случае (если не учесть особенности) программа просто будет занимать много памяти, а не падать в корку. И, плюс, появляется некоторая большая свобода действий, когда не надо вручную за памятью следить.
                                                                                                                                                                        Цитата
                                                                                                                                                                        Потому что в худшем случае (если не учесть особенности) программа просто будет занимать много памяти, а не падать в корку.

                                                                                                                                                                        Если нужна программа, которая будет работать очень непродолжительное время, то память можно вообще не чистить. ;) Но вот что делать с приложениями, которые должны работать годами? Насколько тяжелее находить и ликвидировать утечки памяти на java?
                                                                                                                                                                        Цитата
                                                                                                                                                                        И, плюс, появляется некоторая большая свобода действий, когда не надо вручную за памятью следить.

                                                                                                                                                                        Помоему проблемы сдвигаются немного в другую сторону. Так, например, приходится заморачиваться выбором GC, настраивать его, вызывать деструкторы вручную...
                                                                                                                                                                          wind, извини если я шото упускаю, но я так и не понял, почему ты игнорируешь запуск сборщика мусора.
                                                                                                                                                                          допусим все ссылки на неиспользумые объекты обнулены или вышли из области видимости, т.е. помечены как неиспользуемые.
                                                                                                                                                                          память под объекты все равно остаётся выделенной.
                                                                                                                                                                          её освобождает gc, к-й запустится когда уже память будет подходить к пределу выделенной.
                                                                                                                                                                          во время работы gc приложение либо остановится, либо может gc почистит в параллельном потоке всё что плохо лежит.
                                                                                                                                                                          как ни крути, а это затормозит работу приложения вообще.
                                                                                                                                                                          так?
                                                                                                                                                                            MAxZ, в данном конкретном случае я бы забил на сборщик мусора (в случае java), а также на освобождение памяти (в случае C++/Delphi).
                                                                                                                                                                              Цитата Alex Forth @
                                                                                                                                                                              Только зачем было заморачиваться с GC, если все равно приходится держать в голове кучу особенностей по времени жизни обьектов?

                                                                                                                                                                              эти трудозатраты незначительны по сравнению с тем как приходится следить за возвращением мусора в с++. кроме того ява не ориетирована не на риал-тайм приложения на атомных электростанциях :) соблюдение некоторых правил позволяет избежать заморочек с освобождением памяти вообще.

                                                                                                                                                                              Добавлено
                                                                                                                                                                              Flex Ferrum, почему? тогда тест должен проходить многократно по кругу например в течении часа-двух.
                                                                                                                                                                              ведь программа на с++ наверное освобождает память?
                                                                                                                                                                                Цитата MAxZ @
                                                                                                                                                                                ведь программа на с++ наверное освобождает память?

                                                                                                                                                                                Необязательно. Вполне можно написать так (опять же, в данном конкретном случае), что освобождение памяти будет дано на откуп системе. Или применена другая стратегия пакетного освобождения занятой памяти.
                                                                                                                                                                                  О, это идея. Нужно протестировать без освобождения памяти!
                                                                                                                                                                                    Цитата Flex Ferrum @
                                                                                                                                                                                    Вполне можно написать так

                                                                                                                                                                                    можно, но писали же наверное с освобождением памяти?
                                                                                                                                                                                      Цитата Alex Forth @
                                                                                                                                                                                      Но вот что делать с приложениями, которые должны работать годами? Насколько тяжелее находить и ликвидировать утечки памяти на java?

                                                                                                                                                                                      Утечек памяти в java вообще-то довольно трудно добиться.

                                                                                                                                                                                      Цитата MAxZ @
                                                                                                                                                                                      её освобождает gc, к-й запустится когда уже память будет подходить к пределу выделенной

                                                                                                                                                                                      MAxZ, когда "память будет подходить к пределу выделенной" нужно будет выкидывать на помойку программу и пересматривать архитектурные решения. До подобного не должно доходить никогда.

                                                                                                                                                                                      Цитата Alex Forth @
                                                                                                                                                                                      Помоему проблемы сдвигаются немного в другую сторону. Так, например, приходится заморачиваться выбором GC, настраивать его, вызывать деструкторы вручную...

                                                                                                                                                                                      Что вы такое говорите? :ph34r: Не нужно ничего настраивать. Это может потребоваться настолько редко, что я даже затрудняюсь привести пример. Разве что пытаться приблизиться к realtime, но для этого существует специальная realtime jvm (к вопросу о том, для чего предназначена java).
                                                                                                                                                                                        Цитата Smike @
                                                                                                                                                                                        О, это идея. Нужно протестировать без освобождения памяти!

                                                                                                                                                                                        А вот мне никак :D STL-контейнеры не уничтожаются без освобождения памяти :)) Хотя. а если их динамически создавать? =))
                                                                                                                                                                                          Цитата wind @
                                                                                                                                                                                          Утечек памяти в java вообще-то довольно трудно добиться.

                                                                                                                                                                                          А вот утечек ресурсов — без проблем.
                                                                                                                                                                                            Цитата
                                                                                                                                                                                            эти трудозатраты незначительны по сравнению с тем как приходится следить за возвращением мусора в с++.

                                                                                                                                                                                            При нормальной архитектуре в с++ никаких проблем. ;)

                                                                                                                                                                                            Цитата

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

                                                                                                                                                                                            Разве освобождать память надо только в риал-тайм ??? А как насчет серверных приложений?

                                                                                                                                                                                            Цитата
                                                                                                                                                                                            Утечек памяти в java вообще-то довольно трудно добиться.

                                                                                                                                                                                            Ошибки в программах тоже не особо часто случаются, но это еще не значит, что их не надо обрабатывать или исправлять. В книге "Горький вкус Java" автор приводил кусок кода, сгенеренный каким-то популярным генератором кода. Там была утечка ;) . Я не знаю насколько это актуально сегодня, но мне как-то стремно исспользовать технологию с такими сюрпризами :ph34r:

                                                                                                                                                                                            Цитата
                                                                                                                                                                                            Что вы такое говорите? Не нужно ничего настраивать. Это может потребоваться настолько редко, что я даже затрудняюсь привести пример.

                                                                                                                                                                                            А как же выбор GC для своего прлиложения? Настройка GC под него же?
                                                                                                                                                                                              wind, если разговор имеет смысл, расскажи пожалуйста как будет происходить освобождение памяти без запуска gc?
                                                                                                                                                                                              а то получается странный диалог какой-то %)

                                                                                                                                                                                              Добавлено
                                                                                                                                                                                              Цитата Alex Forth @
                                                                                                                                                                                              При нормальной архитектуре в с++ никаких проблем.

                                                                                                                                                                                              ты счастлив?
                                                                                                                                                                                              так в чом проблема?

                                                                                                                                                                                              Цитата Alex Forth @
                                                                                                                                                                                              Разве освобождать память надо только в риал-тайм ?

                                                                                                                                                                                              зачем вырывать слова из контекста?
                                                                                                                                                                                                Цитата Smike @
                                                                                                                                                                                                О, это идея. Нужно протестировать без освобождения памяти!

                                                                                                                                                                                                Хе 8-) Smike, а кто вам сказал, что память не освобождается? ;)

                                                                                                                                                                                                Цитата mo3r @
                                                                                                                                                                                                А вот утечек ресурсов — без проблем.

                                                                                                                                                                                                О каких ресурсах речь?

                                                                                                                                                                                                Цитата MAxZ @
                                                                                                                                                                                                wind, если разговор имеет смысл, расскажи пожалуйста как будет происходить освобождение памяти без запуска gc?

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

                                                                                                                                                                                                Цитата Alex Forth @
                                                                                                                                                                                                Я не знаю насколько это актуально сегодня, но мне как-то стремно исспользовать технологию с такими сюрпризами :ph34r:

                                                                                                                                                                                                Стрёмно использовать какую-либо технологию, не зная её. Использовать C++ с его сюрпризами гораздо страшнее (сюрпризов неизмеримо больше), если не учитывать один нюанс: это сюрпризы только для новичков ;)
                                                                                                                                                                                                Сообщение отредактировано: wind -
                                                                                                                                                                                                  Цитата wind @
                                                                                                                                                                                                  О каких ресурсах речь?

                                                                                                                                                                                                  Файловые дескрипторы, незавершенные транзакции, объекты GDI в windows, сетевые соединения, в общем, много всего. Из-за особенностей GC в яве и .net такие объекты уничтожаются недетерминированно, и очень легко их упустить.
                                                                                                                                                                                                    Цитата
                                                                                                                                                                                                    ты счастлив?
                                                                                                                                                                                                    так в чом проблема?

                                                                                                                                                                                                    Похоливарить хочу :)
                                                                                                                                                                                                    Цитата
                                                                                                                                                                                                    зачем вырывать слова из контекста?

                                                                                                                                                                                                    Имелось виду, что если основной функциональностью программы является длительная обработка данных, которые постоянно поступают извне, то память рано или поздно прийдется чистить. От этого никуда не деться :( .
                                                                                                                                                                                                    Создатели Java проделали офигенную работу по созданию GC. Думаю, эта работа работа еще не закончена и GC еще много раз изменится. Но несмотря на это, я не вижу чтобы GC был уж очень удобен в использовании. Нет, ну конечно у него есть определенные достоинства, но не стоит забывать и про недостатки.
                                                                                                                                                                                                    Цитата
                                                                                                                                                                                                    В данном примере нет возможности наблюдать работу gc

                                                                                                                                                                                                    А почему бы не вызвать его явно?

                                                                                                                                                                                                    ЗЫ: Если весь мир перейдет на JAVA, то пойду на санки писать java-машины :D
                                                                                                                                                                                                      Цитата mo3r @
                                                                                                                                                                                                      Файловые дескрипторы, незавершенные транзакции, объекты GDI в windows, сетевые соединения, в общем, много всего. Из-за особенностей GC в яве и .net такие объекты уничтожаются недетерминированно, и очень легко их упустить.

                                                                                                                                                                                                      Про .net ничего не скажу - я нетоненавистник :D В java вы должны заботиться об управлении ресурсами ОС в том случае, если вы делаете нативные вызовы, и совершенно не обязательно уничтожать такие ресурсы именно при сборке мусорщиком. Нормальная же java программа никак не общается с такими ресурсами напрямую (именно это, как вы понимаете, и обеспечивает переносимость).

                                                                                                                                                                                                      Цитата Alex Forth @
                                                                                                                                                                                                      Но несмотря на это, я не вижу чтобы GC был уж очень удобен в использовании. Нет, ну конечно у него есть определенные достоинства, но не стоит забывать и про недостатки.

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

                                                                                                                                                                                                      Единственный же недостаток - отъедает часть времени выполнения, причём неизвестно в какой момент; если кого-то этот нюанс сильно смущает (а это может быть важно только при общении с периферией, для которой важно время отклика), предусмотрена возможность тонкой настройки и, наконец, jvm реального времени. Надо заметить, что этот самый нюанс в принципе не должен волновать умы программеров, пишущих под многозаданые ОС.

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

                                                                                                                                                                                                      Цитата Alex Forth @
                                                                                                                                                                                                      А почему бы не вызвать его явно?

                                                                                                                                                                                                      Этого делать нельзя. Да и единственный способ вызвать коллектор руками ничего гарантирует; у коллекторов свой жизненный цикл и, к счастью, вмешаться в него из программы невозможно.
                                                                                                                                                                                                        Цитата wind @
                                                                                                                                                                                                        Нормальная же java программа никак не общается с такими ресурсами напрямую (именно это, как вы понимаете, и обеспечивает переносимость).

                                                                                                                                                                                                        Да-да, и файлы не открывает, и по сети не общается, и в БД не лезет. Скажем, написать примерно такой код:
                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                          class Class1
                                                                                                                                                                                                          {
                                                                                                                                                                                                            public void DoSometing (string fileName)
                                                                                                                                                                                                            {
                                                                                                                                                                                                               File f = new File(fileName);//не знаю точно, как в java файл открыть
                                                                                                                                                                                                               //... тут что-нибудь
                                                                                                                                                                                                               //f.Close(); //<-- закомментировано.
                                                                                                                                                                                                            }
                                                                                                                                                                                                          }

                                                                                                                                                                                                        И получим типичную утечку ресурсов.
                                                                                                                                                                                                        Цитата wind @
                                                                                                                                                                                                        Насчёт удобства использования - это вы загнули. Насколько еще может быть удобнее механизм, о котором никогда не приходиться вспоминать?

                                                                                                                                                                                                        О явовском gc надо вспоминать... В том числе, из-за недетерминированного уничтожения объектов.
                                                                                                                                                                                                        Цитата wind @
                                                                                                                                                                                                        А вот реальных утечек памяти мне пока наблюдать не приходилось, равзе что только свои собственные ошибки, в результате которых объекты не освобождались, а оседали где-нить ссылками.

                                                                                                                                                                                                        А это и есть утечка.
                                                                                                                                                                                                          Цитата mo3r @
                                                                                                                                                                                                          class Class1 { public void DoSometing (string fileName) { File f = new File(fileName);//не знаю точно, как в java файл открыть //... тут что-нибудь //f.Close(); //<-- закомментировано. } }

                                                                                                                                                                                                          Сборщик мусора -> деструктор. А почему бы и нет? =))
                                                                                                                                                                                                            Цитата Мяут @
                                                                                                                                                                                                            Сборщик мусора -> деструктор. А почему бы и нет? =))

                                                                                                                                                                                                            Только когда ;) Сборщик мусора может и через год не добраться до этого файла. (И не деструктор, а финализатор...)
                                                                                                                                                                                                              Цитата mo3r @
                                                                                                                                                                                                              Да-да, и файлы не открывает, и по сети не общается, и в БД не лезет.

                                                                                                                                                                                                              Вы упустили ключевое слово из контекста: напрямую.

                                                                                                                                                                                                              Цитата mo3r @
                                                                                                                                                                                                              Скажем, написать примерно такой код:
                                                                                                                                                                                                              <...>
                                                                                                                                                                                                              И получим типичную утечку ресурсов.

                                                                                                                                                                                                              Может быть мне кто-то подскажет, при чём тут java вообще, не говоря уже о сборщике мусора?

                                                                                                                                                                                                              Цитата mo3r @
                                                                                                                                                                                                              О явовском gc надо вспоминать...

                                                                                                                                                                                                              Нет, не надо. Будем спорить?

                                                                                                                                                                                                              Цитата mo3r @
                                                                                                                                                                                                              А это и есть утечка.

                                                                                                                                                                                                              Это не те утечки, которые мы обсуждаем. Речь о том, кто виноват и следует ли ожидать от программного механизма чудес. Например, я забываю в переменных нитей (нити в пуле) ссылки на коллекции объектов - должен ли сборщик догадаться о том, что это мусор?
                                                                                                                                                                                                                Цитата wind @
                                                                                                                                                                                                                Вы упустили ключевое слово из контекста: напрямую.

                                                                                                                                                                                                                А без разницы, как: напрямую или нет. Все равно есть объект, которые внутри себя держит ресурсы, и если не позаботится, то неизвестно, когда эти ресурсы будут освобождены.
                                                                                                                                                                                                                Цитата wind @
                                                                                                                                                                                                                Может быть мне кто-то подскажет, при чём тут java вообще, не говоря уже о сборщике мусора?

                                                                                                                                                                                                                При том, что это — код на яве, в котором показано, как легко получить утечку ресурсов.
                                                                                                                                                                                                                Цитата wind @
                                                                                                                                                                                                                Это не те утечки, которые мы обсуждаем.

                                                                                                                                                                                                                Те самые. Явовский и дотнетовский gc решает (и то, частично) только задачу управления памятью, а управление ресурсами там не доделано.
                                                                                                                                                                                                                Цитата wind @
                                                                                                                                                                                                                Например, я забываю в переменных нитей (нити в пуле) ссылки на коллекции объектов - должен ли сборщик догадаться о том, что это мусор?

                                                                                                                                                                                                                Если нить прибивается, то, конечно, должен. Если ссылки нигде далее не используются, и это можно простым формальным образом доказать, то да.
                                                                                                                                                                                                                  Цитата mo3r @
                                                                                                                                                                                                                  А без разницы, как: напрямую или нет. Все равно есть объект, которые внутри себя держит ресурсы, и если не позаботится, то неизвестно, когда эти ресурсы будут освобождены.

                                                                                                                                                                                                                  Цитата mo3r @
                                                                                                                                                                                                                  При том, что это — код на яве, в котором показано, как легко получить утечку ресурсов.

                                                                                                                                                                                                                  Точно так же ресурс утечёт на любом другом языке и платформе. Так что я не понимаю, при чём здесь java.

                                                                                                                                                                                                                  Цитата mo3r @
                                                                                                                                                                                                                  Те самые. Явовский и дотнетовский gc решает (и то, частично) только задачу управления памятью, а управление ресурсами там не доделано.

                                                                                                                                                                                                                  И слава Богу. Ещё не хватало, чтобы внутренний механизм программы сам решал, что делать с ресурсами, не им предоставленными.

                                                                                                                                                                                                                  Цитата mo3r @
                                                                                                                                                                                                                  Если нить прибивается, то, конечно, должен. Если ссылки нигде далее не используются, и это можно простым формальным образом доказать, то да.

                                                                                                                                                                                                                  Ни то, ни другое.
                                                                                                                                                                                                                    Цитата wind @
                                                                                                                                                                                                                    Точно так же ресурс утечёт на любом другом языке и платформе. Так что я не понимаю, при чём здесь java.

                                                                                                                                                                                                                    Не обязательно. Например, взять код на C++, который использует семантику копирования или перемещения объектов — в нем утечек ресурсов не будет.
                                                                                                                                                                                                                    ExpandedWrap disabled
                                                                                                                                                                                                                      void read_from_file(string file_name)
                                                                                                                                                                                                                      {
                                                                                                                                                                                                                        ifstream file = ifstream(file_name);
                                                                                                                                                                                                                        //тут что-нибудь
                                                                                                                                                                                                                      }

                                                                                                                                                                                                                    Этот код свободен от утечек. Аналогичным образом на C++ реализуется библиотека типов, свободных от утечек ресурсов (например, в djvulibre используется такой подход).
                                                                                                                                                                                                                    Цитата wind @
                                                                                                                                                                                                                    Ещё не хватало, чтобы внутренний механизм программы сам решал, что делать с ресурсами, не им предоставленными.

                                                                                                                                                                                                                    Скажем так, было бы очень неплохо, если бы был механизм, который бы смог определить, что ресурс более не понадобится и закрыть его сразу же.
                                                                                                                                                                                                                      Цитата mo3r @
                                                                                                                                                                                                                      ifstream file = ifstream(file_name); //тут что-нибудь

                                                                                                                                                                                                                      что это - "что-нибудь"? :D
                                                                                                                                                                                                                        Цитата MAxZ @
                                                                                                                                                                                                                        что это - "что-нибудь"? :D

                                                                                                                                                                                                                        Например, чтение из файла :) Или выкидывание исключение — не важно, что, главное, что файл в любом случае окажется закрыт, и утечки ресурсов не возникнет.
                                                                                                                                                                                                                          Цитата mo3r @
                                                                                                                                                                                                                          Не обязательно. Например, взять код на C++, который использует семантику копирования или перемещения объектов — в нем утечек ресурсов не будет.
                                                                                                                                                                                                                          <...>
                                                                                                                                                                                                                          Этот код свободен от утечек. Аналогичным образом на C++ реализуется библиотека типов, свободных от утечек ресурсов (например, в djvulibre используется такой подход).

                                                                                                                                                                                                                          Так вот оно в чём дело :D Вы сетуете на отсутствие деструкторов, а я всё голову ломаю - при чём же здесь сборка мусора. А если так:
                                                                                                                                                                                                                          ExpandedWrap disabled
                                                                                                                                                                                                                            void read_from_file(string file_name)
                                                                                                                                                                                                                            {
                                                                                                                                                                                                                              ifstream* fileptr = new ifstream(file_name);
                                                                                                                                                                                                                              //тут что-нибудь
                                                                                                                                                                                                                            }
                                                                                                                                                                                                                          ?

                                                                                                                                                                                                                          Цитата mo3r @
                                                                                                                                                                                                                          Скажем так, было бы очень неплохо, если бы был механизм, который бы смог определить, что ресурс более не понадобится и закрыть его сразу же.

                                                                                                                                                                                                                          Такой механизм сможет работать только если сам будет ресурс и выдавать. Если пытаться сделать что-то подобное механизму распределения памяти в java, придётся встроить любые операции с этим ресурсом в язык. И теперь представьте себе язык программирования с парой десятков тысяч ключевых слов :wacko:
                                                                                                                                                                                                                            Цитата wind @
                                                                                                                                                                                                                            А если так:

                                                                                                                                                                                                                            Так — утечка. Но суть в том, что в C++ вполне можно сделать объектные системы без утечек. В java и c# надо внимательно следить за тем, есть ли у объекта финализатор. А если объектная система нетривиальная, то сразу неочевидно, имеет ли объект финализатор, и надо ли его оборачивать в try/finally или using. Это и может стать причиной ошибок или необходимости писать код с большой вложенностью блоков при одновременном использовании нескольких объектов с финализаторами в одной области видимости.
                                                                                                                                                                                                                            Цитата wind @
                                                                                                                                                                                                                            придётся встроить любые операции с этим ресурсом в язык. И теперь представьте себе язык программирования с парой десятков тысяч ключевых слов :wacko:

                                                                                                                                                                                                                            Необязательно.

                                                                                                                                                                                                                            Добавлено
                                                                                                                                                                                                                            Цитата wind @
                                                                                                                                                                                                                            при чём же здесь сборка мусора

                                                                                                                                                                                                                            Сборка мусора при том, что ее реализация в java и .net такова, что не гарантирует время выполнения финализаторов и вообще не гарантирует, что они будут выполнены.
                                                                                                                                                                                                                              Цитата mo3r @
                                                                                                                                                                                                                              Так — утечка.

                                                                                                                                                                                                                              То есть мы таки выяснили, что java (или какой другой язык/платформа) тут совершенно не при чём.

                                                                                                                                                                                                                              Цитата mo3r @
                                                                                                                                                                                                                              Сборка мусора при том, что ее реализация в java и .net такова, что не гарантирует время выполнения финализаторов и вообще не гарантирует, что они будут выполнены.

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

                                                                                                                                                                                                                              Кроме того, всё было бы очень логично, если бы существовала бы в природе такая вещь, как финализатор. У класса может быть несколько "финализаторов", и попытка привязать их к областям действия или еще к чему-нибудь ни к чему хорошему не приведёт. Так что зря вы пытаетесь приплести сюда сборку мусора.

                                                                                                                                                                                                                              Цитата mo3r @
                                                                                                                                                                                                                              Необязательно.

                                                                                                                                                                                                                              И как вы себе представляете, например, автоматическое закрытие файла, открытого вызовом функции осёвого api?
                                                                                                                                                                                                                                Я не понял, а где тогда будут "плюшки" при исользовании GC???
                                                                                                                                                                                                                                  Цитата Alex Forth @
                                                                                                                                                                                                                                  Я не понял, а где тогда будут "плюшки" при исользовании GC???

                                                                                                                                                                                                                                  ???
                                                                                                                                                                                                                                    Ну производительность у него похуже будет, масштабируемость тоже. Особых удобств при его использовании тоже нету. Зачем он вообще нужен?
                                                                                                                                                                                                                                      Цитата Alex Forth @
                                                                                                                                                                                                                                      Ну производительность у него похуже будет, масштабируемость тоже.

                                                                                                                                                                                                                                      Что такое масштабируемость в вашем понимании?

                                                                                                                                                                                                                                      Цитата Alex Forth @
                                                                                                                                                                                                                                      Особых удобств при его использовании тоже нету.

                                                                                                                                                                                                                                      Это какие такие удобства окромя отсутствия необходимости заботиться об уничтожении объектов в памяти от него требуются?
                                                                                                                                                                                                                                        Для сервера нам нужен один тип GC, для реал-тайм другой и т д. Вот такая она масштабируемость :(
                                                                                                                                                                                                                                        В книгах по java обычно пишут, что про удаление памяти можно забыть, а тут оказывается не все так просто :( . И утечку можно организовать и финализаторы надо явно вызывать.
                                                                                                                                                                                                                                          Цитата Alex Forth @
                                                                                                                                                                                                                                          Для сервера нам нужен один тип GC, для реал-тайм другой и т д. Вот такая она масштабируемость :(

                                                                                                                                                                                                                                          А что, может быть как-то иначе? Нет, я понимаю, что можно сделать нечто универсальное, но лично я против. Универсальное - значит одинаково плохое в любом из случаев.

                                                                                                                                                                                                                                          Цитата Alex Forth @
                                                                                                                                                                                                                                          В книгах по java обычно пишут, что про удаление памяти можно забыть, а тут оказывается не все так просто :( И утечку можно организовать <...>

                                                                                                                                                                                                                                          Не нужно ожидать недюжинных интеллектуальных и телепатических способностей jvm - если не отпускать объекты, они никуда не денутся - будет вам утечка.

                                                                                                                                                                                                                                          Цитата Alex Forth @
                                                                                                                                                                                                                                          <...> и финализаторы надо явно вызывать.

                                                                                                                                                                                                                                          "Финализаторы" нужно будет вызывать явно всегда. Нет и не будет такой платформы, где от этого можно будет избавиться.
                                                                                                                                                                                                                                          В java нет деструкторов, но модифицированный пример mo3r'а показывает, что их ценность с точки зрения контроля за ресурсами эфемерна.
                                                                                                                                                                                                                                            Цитата
                                                                                                                                                                                                                                            А что, может быть как-то иначе? Нет, я понимаю, что можно сделать нечто универсальное, но лично я против. Универсальное - значит одинаково плохое в любом из случаев.

                                                                                                                                                                                                                                            А чем лично вам ненравится явное удаление, как более универсальный механизм?
                                                                                                                                                                                                                                            Цитата
                                                                                                                                                                                                                                            Не нужно ожидать недюжинных интеллектуальных и телепатических способностей jvm - если не отпускать объекты, они никуда не денутся - будет вам утечка.

                                                                                                                                                                                                                                            Тоесть, если раньше был явный delete, то теперь он завуалирован обнулением?
                                                                                                                                                                                                                                            Цитата
                                                                                                                                                                                                                                            "Финализаторы" нужно будет вызывать явно всегда.

                                                                                                                                                                                                                                            Мне не нравится, что в java надо отдельно следить за памятью и отдельно за остальными ресурсами. Для обьекта все должно удаляться в одном месте. Так и код понимать легче и меньше предпосылок к ошибкам.
                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                              И как вы себе представляете, например, автоматическое закрытие файла, открытого вызовом функции осёвого api?

                                                                                                                                                                                                                                              В C++ можно создать простой класс: в констукторе открываем, в деструкторе - закрываем. Обычно конец области видимости объекта класса можно считать тем самым местом, где надобность в объекте (и данном случае - захваченных им ресурсах) отпадает. Собственно, пример уже был:

                                                                                                                                                                                                                                              ExpandedWrap disabled
                                                                                                                                                                                                                                                void read_from_file(string file_name)
                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                    ifstream file(file_name);
                                                                                                                                                                                                                                                    ... // работаем с файлом
                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                } // здесь (при выходе из функции) файл больше не нужен,
                                                                                                                                                                                                                                                  // и он будет _автоматически_ закрыт,
                                                                                                                                                                                                                                                  // независимо от того, по какой причине мы сюда попадём


                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                              В java нет деструкторов, но модифицированный пример mo3r'а показывает, что их ценность с точки зрения контроля за ресурсами эфемерна.

                                                                                                                                                                                                                                              Отнюдь. Использование new вкупе с сырыми указателями означает добровольный отказ от автоматического контроля за временем жизни объекта. Но это никак не отменяет того, что автоматический контроль за временем жизни объекта (и захваченными им ресурсами) в C++ возможен (и вышеприведённый пример показывает, насколько он прост и понятен). А как обстоят дела с автоматическим освобождением ресурсов в Java?
                                                                                                                                                                                                                                              Сообщение отредактировано: Dantes -
                                                                                                                                                                                                                                                Цитата wind @
                                                                                                                                                                                                                                                "Финализаторы" нужно будет вызывать явно всегда. Нет и не будет такой платформы, где от этого можно будет избавиться.

                                                                                                                                                                                                                                                Хмм. C++ - вот такая платформа. :)


                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                В java нет деструкторов, но модифицированный пример mo3r'а показывает, что их ценность с точки зрения контроля за ресурсами эфемерна.

                                                                                                                                                                                                                                                Это который тобой модицифированный? Так это не показатель. Во-первых, динамические переменные не так часто используются - всегда стараются юзать автоматические, во-вторых, у опытных программистов голые указатели не используются для хранения указателей на объекты - есть разнообразные классы умных указателей. Так что RAII как было так и есть.

                                                                                                                                                                                                                                                Вообще, вроде давно было сказано, что основное преимущества Java перед C++ - это более низкие требования к квалификации программиста - нужен гораздо меньший опыт, чтобы что-нибудь худо-бедно работающее родить. А чем выше квалификация - тем меньше это преимущество влияет. Зато выходит на передний план контроль за ресурсами. Если в C++ можно контроль за любым ресурсом при желании сделать автоматическим, использую идиому RAII, то в Java дается только автоматический контроль за памятью, и то с возможность утечки.
                                                                                                                                                                                                                                                  Цитата Alex Forth @
                                                                                                                                                                                                                                                  А чем лично вам ненравится явное удаление, как более универсальный механизм?

                                                                                                                                                                                                                                                  Неудобством. Начав программировать на java я уже не готов отказаться от автоматической сборки мусора.

                                                                                                                                                                                                                                                  Цитата Alex Forth @
                                                                                                                                                                                                                                                  Тоесть, если раньше был явный delete, то теперь он завуалирован обнулением?

                                                                                                                                                                                                                                                  Явное обнуления ссылок требуется только в особых (естественных) случаях - циклические ссылки и/или долгоживущие контейнеры.

                                                                                                                                                                                                                                                  Цитата Alex Forth @
                                                                                                                                                                                                                                                  Мне не нравится, что в java надо отдельно следить за памятью и отдельно за остальными ресурсами. Для обьекта все должно удаляться в одном месте. Так и код понимать легче и меньше предпосылок к ошибкам.

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

                                                                                                                                                                                                                                                  Цитата Dantes @
                                                                                                                                                                                                                                                  Отнюдь. Использование new вкупе с сырыми указателями означает добровольный отказ от автоматического контроля за временем жизни объекта. Но это никак не отменяет того, что автоматический контроль за временем жизни объекта (и захваченными им ресурсами) в C++ возможен (и вышеприведённый пример показывает, насколько он прост и понятен).

                                                                                                                                                                                                                                                  Теоретически возможен, скажем так. Я не уверен, что можно полностью отказаться от использования операции new.

                                                                                                                                                                                                                                                  Кстати, а как ловят исключения в деструкторе (в том же примере)?

                                                                                                                                                                                                                                                  Цитата Hryak @
                                                                                                                                                                                                                                                  Хмм. C++ - вот такая платформа.

                                                                                                                                                                                                                                                  В упор не вижу такой возможности. На примере, плз, с несколькими (в т. ч. параметризуемыми "финализаторами").
                                                                                                                                                                                                                                                    Цитата wind @
                                                                                                                                                                                                                                                    Абсолютно везде нужно отдельно следить за ресурсами.

                                                                                                                                                                                                                                                    В С++, используя RAII, почему то не нужно...

                                                                                                                                                                                                                                                    Цитата
                                                                                                                                                                                                                                                    Кстати, а как ловят исключения в деструкторе (в том же примере)?

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

                                                                                                                                                                                                                                                    Цитата
                                                                                                                                                                                                                                                    Цитата Hryak @
                                                                                                                                                                                                                                                    Хмм. C++ - вот такая платформа.

                                                                                                                                                                                                                                                    В упор не вижу такой возможности. На примере, плз, с несколькими (в т. ч. параметризуемыми "финализаторами").

                                                                                                                                                                                                                                                    Дык уже сто раз приведенный ifstream file ... Ресурс есть - есть. Автоматическое слежение за ресурсом с освобождением ресурса сразу же за окончанием работы с ним есть - есть. ЧТо еще надо?
                                                                                                                                                                                                                                                      Цитата Hryak @
                                                                                                                                                                                                                                                      Ислючение прекрасно ловится в деструкторе, вот только не всегда его можно выпустить за пределы деструктора. Но это не является сколь-нибудь критическим ограничением.

                                                                                                                                                                                                                                                      Что, в самом деле? Если например, не удаётся закрыть файл по какой-то причине (юзаем тот же пример) - исключение всегда нужно выбрасывать наверх.

                                                                                                                                                                                                                                                      Цитата Hryak @
                                                                                                                                                                                                                                                      Ресурс есть - есть. Автоматическое слежение за ресурсом с освобождением ресурса сразу же за окончанием работы с ним есть - есть. ЧТо еще надо?

                                                                                                                                                                                                                                                      Я уже высказал пожелания. Есть класс, есть методы для финализации. Их два, один из них с параметром. Как мне добиться того, чтобы компилятор угадал, какой мне нужно вызвать при выходе за область видимости объекта, да еще подставил нужный мне параметр?
                                                                                                                                                                                                                                                        Цитата wind @
                                                                                                                                                                                                                                                        Теоретически возможен, скажем так.

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

                                                                                                                                                                                                                                                        Цитата wind @
                                                                                                                                                                                                                                                        Я не уверен, что можно полностью отказаться от использования операции new.

                                                                                                                                                                                                                                                        Тут, скорее, нужно вести речь о необходимости явно вызывать delete (при работе с сырыми указателями). Такие случаи есть, но они редки, и, как правило, такие явные вызовы new/delete всё же удаётся инкапсулировать в каком-нибудь классе (причём низкоуровневом).

                                                                                                                                                                                                                                                        Цитата wind @
                                                                                                                                                                                                                                                        Кстати, а как ловят исключения в деструкторе (в том же примере)?

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

                                                                                                                                                                                                                                                        Цитата wind @
                                                                                                                                                                                                                                                        В упор не вижу такой возможности. На примере, плз, с несколькими (в т. ч. параметризуемыми "финализаторами").

                                                                                                                                                                                                                                                        В C++ нет финализаторов (в силу поддержки идиомы RAII, они там в общем-то и не нужны).
                                                                                                                                                                                                                                                        Сообщение отредактировано: Dantes -
                                                                                                                                                                                                                                                          Цитата Dantes @
                                                                                                                                                                                                                                                          Так же, как и не в деструкторе, только с той разницей, что ловить надо все исключения, дабы не позволить им покинуть деструктор.

                                                                                                                                                                                                                                                          Цитата Dantes @
                                                                                                                                                                                                                                                          В C++ нет финализаторов (в силу поддержки идиомы RAII, они там в общем-то и не нужны).

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

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

                                                                                                                                                                                                                                                            Для C++ такой подход не годится. Если не удаётся закрыть файл (интересно, почему?), то проблему следует решать в месте её возникновения.

                                                                                                                                                                                                                                                            Стандартные файловые потоки всегда закрывают файлы без каких-либо сбоев.

                                                                                                                                                                                                                                                            Цитата wind
                                                                                                                                                                                                                                                            Маленький пример: имеет место длительная транзакция, в рамках которой нужно считать некоторые файлы, обработать, создать файлы с выходными данными. При успешной обработке вызывается некоторый сервис, который подцепит результаты. Если обломится запись хоть одного из них, то все уже созданные должны быть уничтожены, сервис не должен получить уведомления

                                                                                                                                                                                                                                                            И какая роль должна отводиться деструкторам?

                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                              class OutputFile
                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                              public:
                                                                                                                                                                                                                                                                  OutputFile(const char* filename) :
                                                                                                                                                                                                                                                                      file(filename), filename(filename) {}
                                                                                                                                                                                                                                                                  // ...
                                                                                                                                                                                                                                                                  void Delete() { file.close(); DeleteFileA(filename.c_str()); }
                                                                                                                                                                                                                                                              private:
                                                                                                                                                                                                                                                                  std::ofstream file;
                                                                                                                                                                                                                                                                  std::string filename;
                                                                                                                                                                                                                                                              };
                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                              void Transaction(std::list<shared_ptr<OutputFile> >& output_file_list)
                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                  // ...
                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                              void f()
                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                  typedef shared_ptr<OutputFile> File;
                                                                                                                                                                                                                                                                  std::list<File> output_file_list; // создаём пустой список
                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                  try
                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                      // Transaction помещает "умные указатели", владеющие создаваемыми
                                                                                                                                                                                                                                                                      // файлами в список
                                                                                                                                                                                                                                                                      Transaction(output_file_list);
                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                  catch (/* тип исключения */)
                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                      // закрываем и удаляем все созданные файлы
                                                                                                                                                                                                                                                                      for (
                                                                                                                                                                                                                                                                          std::list<File>::iterator it = output_file_list.begin();
                                                                                                                                                                                                                                                                          it != output_file_list.end();
                                                                                                                                                                                                                                                                          ++it)
                                                                                                                                                                                                                                                                              (*it)->Delete();
                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                  // если файлы не закрыты, то они автоматически закроются
                                                                                                                                                                                                                                                                  // при выходе из функции
                                                                                                                                                                                                                                                              }


                                                                                                                                                                                                                                                            Добавлено
                                                                                                                                                                                                                                                            Можно добавить ещё один класс - чтобы создание файла и занесение его в список делались в одном месте

                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                              class OutputFile
                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                  //...
                                                                                                                                                                                                                                                              public:
                                                                                                                                                                                                                                                                  std::ofstream& Stream() { return file; }
                                                                                                                                                                                                                                                                  //...
                                                                                                                                                                                                                                                              };
                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                              class OutFile
                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                              public:
                                                                                                                                                                                                                                                                  OutFile(const char* filename, std::list<shared_ptr<OutputFile> >& list) :
                                                                                                                                                                                                                                                                      file(new OutputFile(filename))
                                                                                                                                                                                                                                                                          { list.push_back(file); }
                                                                                                                                                                                                                                                                  const std::ofstream& Stream() const { return file->Stream(); }
                                                                                                                                                                                                                                                                  std::ofstream& Stream() { return file->Stream(); }
                                                                                                                                                                                                                                                              private:
                                                                                                                                                                                                                                                                  shared_ptr<OutputFile> file;
                                                                                                                                                                                                                                                              };
                                                                                                                                                                                                                                                            Сообщение отредактировано: Dantes -
                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                              Если не удаётся закрыть файл (интересно, почему?), то проблему следует решать в месте её возникновения.

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

                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                              Стандартные файловые потоки всегда закрывают файлы без каких-либо сбоев.

                                                                                                                                                                                                                                                              Вы уж простите, но это уже похоже на затыкание пробоин в плавсредстве плевками :lol: Во-первых, могут быть и нестандартные потоки (и нестандартные реализации стандартных потоков), во-вторых вряд ли стоит рассчитывать на то, что ваша програма будет выполняться в идеальных условиях. Если сбой может произойти, он непременно произойдёт и это следует учитывать.
                                                                                                                                                                                                                                                              Сообщение отредактировано: wind -
                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                Например, на диске кончилось место и не удалось записать данные буфера. Сам по себе класс, инкапсулирующий в себе работу с файлом, эту проблему решить не в состоянии

                                                                                                                                                                                                                                                                В таком случае нужно предварительно сообщать объекту, который работает с файлом, функцию или функтор-обработчик такой ситуации.

                                                                                                                                                                                                                                                                Цитата
                                                                                                                                                                                                                                                                и ваш пример в этом случае работать не будет

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

                                                                                                                                                                                                                                                                В данном случае можно обойтись и списком имён файлов:

                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                  // собственный класс для работы с файлом
                                                                                                                                                                                                                                                                  class OutputFile
                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                  public:
                                                                                                                                                                                                                                                                      template <class ErrHandler>
                                                                                                                                                                                                                                                                          OutputFile(const char* filename, const ErrHandler& err_handler) :
                                                                                                                                                                                                                                                                              err_handler(err_handler) //...
                                                                                                                                                                                                                                                                      ~OutputFile()
                                                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                                                          //...
                                                                                                                                                                                                                                                                          if (/*...*/)        // если возникла ошибка
                                                                                                                                                                                                                                                                              err_handler();  // вызываем обработчик
                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                      //...
                                                                                                                                                                                                                                                                  private:
                                                                                                                                                                                                                                                                      boost::function<void ()> err_handler;
                                                                                                                                                                                                                                                                      //...
                                                                                                                                                                                                                                                                  };
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                  // функтор - обработчик ошибки
                                                                                                                                                                                                                                                                  class TransactionErrHandler
                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                  public:
                                                                                                                                                                                                                                                                      TransactionErrHandler(bool& fail) : fail(fail)
                                                                                                                                                                                                                                                                      void operator ()() const { fail = true; }
                                                                                                                                                                                                                                                                  private:
                                                                                                                                                                                                                                                                      bool& fail;
                                                                                                                                                                                                                                                                  };
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                  void Transaction(std::list<std::string>& filenames, bool& fail)
                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                      // ...
                                                                                                                                                                                                                                                                      OutputFile file(file_name, TransactionErrHandler(fail));
                                                                                                                                                                                                                                                                      filenames.push_back(file_name);
                                                                                                                                                                                                                                                                      // ...
                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                  void UseTransaction()
                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                      std::list<std::string> filenames;
                                                                                                                                                                                                                                                                      bool fail = false;
                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                      try
                                                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                                                          Transaction(filenames, fail);
                                                                                                                                                                                                                                                                          if (fail)
                                                                                                                                                                                                                                                                              throw exception_type();
                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                      catch (exception_type)
                                                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                                                          for (
                                                                                                                                                                                                                                                                              std::list<std::string>::iterator it = filenames.begin();
                                                                                                                                                                                                                                                                              it != filenames.end();
                                                                                                                                                                                                                                                                              ++it)
                                                                                                                                                                                                                                                                                  DeleteFileA(it->c_str());
                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                  }

                                                                                                                                                                                                                                                                Ссылку на состояние fail можно передавать вместе со списком имён, либо можно возвращать состояние из функции Transaction.
                                                                                                                                                                                                                                                                Сообщение отредактировано: Dantes -
                                                                                                                                                                                                                                                                  Цитата Dantes @
                                                                                                                                                                                                                                                                  В таком случае нужно предварительно сообщать объекту, который работает с файлом, функцию или функтор-обработчик такой ситуации.

                                                                                                                                                                                                                                                                  Цитата Dantes @
                                                                                                                                                                                                                                                                  Повторюсь, насколько я знаю, файловые потоки C++ всегда закрывают файлы успешно. Если же вместо стандартного ofstream использовать другой класс, где закрытие файла может пройти неудачно, то нужно, как я уже отметил выше, осуществлять вызов специального обработчика.

                                                                                                                                                                                                                                                                  Чиним движок через выхлопную трубу, ага :D Иными словами, Dantes, это уже извращения. Ладно уже, давайте прекратим оффтоп и останемся каждый при своём.
                                                                                                                                                                                                                                                                    Цитата wind
                                                                                                                                                                                                                                                                    Иными словами, Dantes, это уже извращения.

                                                                                                                                                                                                                                                                    А что, в Java ошибки в финализации обрабатываются как-то элегантнее?

                                                                                                                                                                                                                                                                    Цитата wind
                                                                                                                                                                                                                                                                    Ладно уже, давайте прекратим оффтоп и останемся каждый при своём.

                                                                                                                                                                                                                                                                    Нетужки, я хочу знать, зачем пошла эта дискуссия про исключения в деструкторах. Что же такого хорошего может противопоставить здесь Java?
                                                                                                                                                                                                                                                                      Цитата Dantes @
                                                                                                                                                                                                                                                                      А что, в Java ошибки в финализации обрабатываются как-то элегантнее?

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

                                                                                                                                                                                                                                                                      Цитата Dantes @
                                                                                                                                                                                                                                                                      Нетужки, я хочу знать, зачем пошла эта дискуссия про исключения в деструкторах. Что же такого хорошего может противопоставить здесь Java?

                                                                                                                                                                                                                                                                      В java нет деструкторов. Соответственно, никакого RAII. Как выяснилось (хотя и так было понятно), исключительно к счастью.
                                                                                                                                                                                                                                                                        Цитата wind @
                                                                                                                                                                                                                                                                        В java (хотя я бы точно так же поступал бы и в C++) я вызываю метод close() потока, который в случае ошибки породит исключение, которое я смогу обработать.

                                                                                                                                                                                                                                                                        А давай подумаем вот над чем. В скольких случаях у тебя close может (реально) выбросить исключение, и в скольких ты можешь элементарно забыть этот close вызвать... :)

                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                        Боюсь, что отношение получится 1 к 100, если не больше...
                                                                                                                                                                                                                                                                          Цитата wind
                                                                                                                                                                                                                                                                          В java (хотя я бы точно так же поступал бы и в C++) я вызываю метод close() потока, который в случае ошибки породит исключение, которое я смогу обработать.

                                                                                                                                                                                                                                                                          А что если ресурсов несколько? Для одного вызвали close - он бросил исключение, что с остальными ресурсами делать?
                                                                                                                                                                                                                                                                            Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                            А давай подумаем вот над чем. В скольких случаях у тебя close может (реально) выбросить исключение, и в скольких ты можешь элементарно забыть этот close вызвать...

                                                                                                                                                                                                                                                                            Ну если брать конкретно меня, то я не забуду close (или его аналог) никогда. Особенно если он параметризован.
                                                                                                                                                                                                                                                                            А исключения на закрытии файлы я ловил за всю практику раз пять, не больше. НО. Основывать механизм, который должен работать аки часы на предположениях... извините. С памятью этот номер пройдёт (потому как у меня нет иных средств для работы с памятью, кроме средств встроенных в язык), с другими ресурсами - нет.

                                                                                                                                                                                                                                                                            Цитата Dantes @
                                                                                                                                                                                                                                                                            А что если ресурсов несколько? Для одного вызвали close - он бросил исключение, что с остальными ресурсами делать?

                                                                                                                                                                                                                                                                            Вот именно. Это уже логика, которую отдавать на откуп какому-то автомату нельзя.
                                                                                                                                                                                                                                                                              Для полноценной работы RAII достаточно ввести требование, что объект всегда можно безопасно закрыть (на самом деле, это достаточно естественное требование, которые выполняется практически везде). И все. И никакие исключения в деструкторах не будут создавать проблем, потому что их там не будет. Таким образом, RAII махом закрывает кучу проблем.
                                                                                                                                                                                                                                                                              Одно из немногих мест, где это может не выполняться — это распределенные транзакции.
                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                Вот именно. Это уже логика, которую отдавать на откуп какому-то автомату нельзя.

                                                                                                                                                                                                                                                                                Это к чему было сказано? Меня интересуют конкретные способы выхода из сложившейся ситуации. Было заявлено, что можно вот так просто вызвать close, потенциально генерирующий исключение, и где-то это исключение выловить. Вот только непонятно, как этот "неизвращённый" способ можно применять при наличии нескольких ресурсов. Освободить-то нужно все ресурсы и любой при освобождении может кинуть исключение. В каком же порядке должны выполняться вызовы close/free/ещё_что-то и обработка лавинно возникающих исключений? Код в студию!
                                                                                                                                                                                                                                                                                  Цитата mo3r @
                                                                                                                                                                                                                                                                                  Для полноценной работы RAII достаточно ввести требование, что объект всегда можно безопасно закрыть (на самом деле, это достаточно естественное требование, которые выполняется практически везде). И все. И никакие исключения в деструкторах не будут создавать проблем, потому что их там не будет. Таким образом, RAII махом закрывает кучу проблем.
                                                                                                                                                                                                                                                                                  Одно из немногих мест, где это может не выполняться — это распределенные транзакции.

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

                                                                                                                                                                                                                                                                                  Цитата Dantes @
                                                                                                                                                                                                                                                                                  Меня интересуют конкретные способы выхода из сложившейся ситуации.
                                                                                                                                                                                                                                                                                  <...>
                                                                                                                                                                                                                                                                                  Код в студию!

                                                                                                                                                                                                                                                                                  В таком случае конкретизируйте задачу. С какого это перепуга я вдруг буду разом открывать те же файлы десятками, да еще меня будет интересовать состояние каждого из них?
                                                                                                                                                                                                                                                                                    Цитата wind @
                                                                                                                                                                                                                                                                                    Что-то не слишком обнадёживает; более одного прецедента - уже система.

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

                                                                                                                                                                                                                                                                                    Но рассмотрим эту ситуацию подробнее. Работу с тем же файлом можно разбить на три стадии
                                                                                                                                                                                                                                                                                    - Открытие файла
                                                                                                                                                                                                                                                                                    - Работа с файлом
                                                                                                                                                                                                                                                                                    - Закрытие файла.

                                                                                                                                                                                                                                                                                    Первые две стадии легко могут кинуть исключение (файла нет, файл не доступен, не хватает места на диске для записи, вышли за пределы файла и т. п.). А вот закрытие файла предполагает, что все возможные проблемы были выявлены на предыдущих стадиях. И само закрытие проблем не вызовет и просто освободит ресурсы.

                                                                                                                                                                                                                                                                                    С этой точки зрения RAII вполне применимо, ибо операции, освобождающие ресурс, если и заканчиваются ошибками, то фатальными для приложения в целом.

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

                                                                                                                                                                                                                                                                                    Да, кстати, ты так и не ответил - как выполнять финализацию в той же джаве в случае, если file.close(), вызванное в блоке финализации, стреляет исключением?
                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                      Что-то не слишком обнадёживает; более одного прецедента - уже система. Возможно, это практически-везде-которое-будет-пригодно-к-использованию-после-модификации-языка-и-при-условии-неиспользования-некоторых-его-возможностей когда-нибудь и оформится в полноценный механизм, но пока...

                                                                                                                                                                                                                                                                                      А это уже сейчас полноценный механизм, который многими успешно используется :)
                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                      более одного прецедента - уже система.

                                                                                                                                                                                                                                                                                      Не совсем. Это — разные классы ситуаций. На самом деле, очень сложно (можно, но сложно) подобрать пример, когда RAII неприменим. Управление ресурсами замечательно вписывается в эту идиому. «Кошерная» обработка распределенных транзакций в нее не очень вписывается. Но с управлением ресурсами справляется замечательно.
                                                                                                                                                                                                                                                                                        Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                        А вот закрытие файла предполагает, что все возможные проблемы были выявлены на предыдущих стадиях.

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

                                                                                                                                                                                                                                                                                        Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                        Да, кстати, ты так и не ответил - как выполнять финализацию в той же джаве в случае, если file.close(), вызванное в блоке финализации, стреляет исключением?

                                                                                                                                                                                                                                                                                        Что-то вроде этого (я обычно делаю не совсем так, здесь нет защиты от ошибок, не связанных с вводом-выводом и штатного закрытия):

                                                                                                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                                                                                                          FileOutputStream fileOutputStream = new FileOutputStream(fileName);
                                                                                                                                                                                                                                                                                          BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                                                                                                                                                                                                                                                                                          try {
                                                                                                                                                                                                                                                                                              ... // запись
                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                          catch (IOException thrown) {
                                                                                                                                                                                                                                                                                              try {
                                                                                                                                                                                                                                                                                                  bufferedOutputStream.close(); // закрываем в любом случае
                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                              catch (IOException thrown) {
                                                                                                                                                                                                                                                                                                  // здесь я могу выбирать - вывести диалог retry/abort/ignore или
                                                                                                                                                                                                                                                                                                  // закрыть fileOutputStream безусловно. Если обломится операция закрытия у
                                                                                                                                                                                                                                                                                                  // fileOutputStream - это уже непостижимо для данного куска кода -
                                                                                                                                                                                                                                                                                                  // исключение будет выброшено наверх.
                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                              // Если это необходимо, кривой файл будет удалён.
                                                                                                                                                                                                                                                                                          }


                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                        Цитата mo3r @
                                                                                                                                                                                                                                                                                        На самом деле, очень сложно (можно, но сложно) подобрать пример, когда RAII неприменим.

                                                                                                                                                                                                                                                                                        Я уже подобрал, довольно быстро - закрытие файлового потока.
                                                                                                                                                                                                                                                                                          Цитата wind @
                                                                                                                                                                                                                                                                                          Только если при закрытии в файл не сбрасывается буфер, т. е. закрытие в данном случае - освобождение ресурса.

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

                                                                                                                                                                                                                                                                                          Добавлено
                                                                                                                                                                                                                                                                                          Цитата wind @
                                                                                                                                                                                                                                                                                          Что-то вроде этого

                                                                                                                                                                                                                                                                                          Жесть... <_<
                                                                                                                                                                                                                                                                                            Цитата wind @
                                                                                                                                                                                                                                                                                            В таком случае конкретизируйте задачу. С какого это перепуга я вдруг буду разом открывать те же файлы десятками, да еще меня будет интересовать состояние каждого из них?

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

                                                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                                                              File file_handle_1 = open_file(filename1); // может генерировать исключения
                                                                                                                                                                                                                                                                                              File file_handle_2 = open_file(filename2); // может генерировать исключения
                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                              // ... попеременно работаем с этими двумя файлами
                                                                                                                                                                                                                                                                                              // (возможен выброс исключения)
                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                              close_file(file_handle_2); // может генерировать исключения
                                                                                                                                                                                                                                                                                              close_file(file_handle_1); // может генерировать исключения

                                                                                                                                                                                                                                                                                            Пока что данный код чреват утечкой ресурсов. Хочу видеть примерный код без утечки ресурсов – можно на Java.

                                                                                                                                                                                                                                                                                            Цитата wind @
                                                                                                                                                                                                                                                                                            Что-то вроде этого

                                                                                                                                                                                                                                                                                            А, это и есть аналог моей задачи?

                                                                                                                                                                                                                                                                                            Цитата wind @
                                                                                                                                                                                                                                                                                            здесь нет защиты от ошибок, не связанных с вводом-выводом и штатного закрытия):

                                                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                                                              FileOutputStream fileOutputStream = new FileOutputStream(fileName);
                                                                                                                                                                                                                                                                                              BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                                                                                                                                                                                                                                                                                              try {
                                                                                                                                                                                                                                                                                                  ... // запись
                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                              catch (IOException thrown) {
                                                                                                                                                                                                                                                                                                  try {
                                                                                                                                                                                                                                                                                                      bufferedOutputStream.close(); // закрываем в любом случае
                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                  catch (IOException thrown) {
                                                                                                                                                                                                                                                                                                      // здесь я могу выбирать - вывести диалог retry/abort/ignore или
                                                                                                                                                                                                                                                                                                      // закрыть fileOutputStream безусловно. Если обломится операция закрытия у
                                                                                                                                                                                                                                                                                                      // fileOutputStream - это уже непостижимо для данного куска кода -
                                                                                                                                                                                                                                                                                                      // исключение будет выброшено наверх.
                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                  // Если это необходимо, кривой файл будет удалён.
                                                                                                                                                                                                                                                                                              }

                                                                                                                                                                                                                                                                                            Здесь нет закрытия файлов при нормальном течении ввода-вывода, а также сопутствующей защиты от ошибок при их ненормальном закрытии. Здесь нет защиты от утечки ресурсов на случай, если

                                                                                                                                                                                                                                                                                            Цитата wind @
                                                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                                                              BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

                                                                                                                                                                                                                                                                                            бросит исключение. Однако код и без этого получился сложным. Про работу с тремя и более ресурсами лучше не вспоминать вообще. Но, помимо сложности, этому коду присущи ещё кое-какие удивительные моменты. Исключение от закрытия одного из файлов мы обрабатываем незамедлительно, а исключение от закрытия другого мы куда-то бросаем. Это по какому же принципу мы так распорядились? И куда, спрашивается, подевалось исключение thrown в первом catch-блоке? Мы ведь его, наверно, не только для того сгенерировали, чтоб файлы закрыть? Почему мы должны полностью обрабатывать это исключение именно в приведённом здесь catch-блоке, а не где-то наверху? А если мы попытаемся перекинуть его наверх, то что тогда делать при неудачном закрытии fileOutputStream во втором catch блоке?

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

                                                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                                                              File file_handle_1 = open_file(filename1);
                                                                                                                                                                                                                                                                                              File file_handle_2;
                                                                                                                                                                                                                                                                                              try
                                                                                                                                                                                                                                                                                                  { file_handle_2 = open_file(filename2); }
                                                                                                                                                                                                                                                                                              catch (failed_opening&)
                                                                                                                                                                                                                                                                                                  { file_handle_1.close(); throw; }
                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                              try
                                                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                                                  // ... попеременно работаем с этими двумя файлами
                                                                                                                                                                                                                                                                                                  // (возможен выброс исключения)
                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                              catch (io_error& err1)
                                                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                                                  try
                                                                                                                                                                                                                                                                                                      { close_file(file_handle_2); }
                                                                                                                                                                                                                                                                                                  catch (failed_closing& err2)
                                                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                                                      try
                                                                                                                                                                                                                                                                                                          { close_file(file_handle_1); }
                                                                                                                                                                                                                                                                                                      catch (failed_closing& err3)
                                                                                                                                                                                                                                                                                                          { throw make_tuple(err1, err2, err3); }
                                                                                                                                                                                                                                                                                                      throw make_tuple(err1, err2);
                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                  try
                                                                                                                                                                                                                                                                                                      { close_file(file_handle_1); }
                                                                                                                                                                                                                                                                                                  catch (failed_closing& err2)
                                                                                                                                                                                                                                                                                                      { throw make_tuple(err1, err2); }
                                                                                                                                                                                                                                                                                                  throw;
                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                              try
                                                                                                                                                                                                                                                                                                  { close_file(file_handle_2); }
                                                                                                                                                                                                                                                                                              catch (failed_closing& err1)
                                                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                                                  try
                                                                                                                                                                                                                                                                                                      { close_file(file_handle_1); }
                                                                                                                                                                                                                                                                                                  catch (failed_closing& err2)
                                                                                                                                                                                                                                                                                                      { throw make_tuple(err1, err2); }
                                                                                                                                                                                                                                                                                                  throw;
                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                              close_file(file_handle_1);

                                                                                                                                                                                                                                                                                            и потом где-то ловить эти синглы, пары, триады, но это исключительно для маньяков :wacko:

                                                                                                                                                                                                                                                                                            Цитата wind @
                                                                                                                                                                                                                                                                                            Я уже подобрал, довольно быстро - закрытие файлового потока.

                                                                                                                                                                                                                                                                                            Плохо подобрал. С такими неправильными потоками - что с RAII, что без - проблем выше крыши.
                                                                                                                                                                                                                                                                                            Сообщение отредактировано: Dantes -
                                                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                                                              Здесь нет закрытия файлов при нормальном течении ввода-вывода, а также сопутствующей защиты от ошибок при их ненормальном закрытии.

                                                                                                                                                                                                                                                                                              Там так и написано: "здесь нет защиты от ошибок, не связанных с вводом-выводом и штатного закрытия".

                                                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                                                              Здесь нет защиты от утечки ресурсов на случай, если
                                                                                                                                                                                                                                                                                              <...>
                                                                                                                                                                                                                                                                                              бросит исключение.

                                                                                                                                                                                                                                                                                              В этом случае утечка невозможна.

                                                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                                                              Однако код и без этого получился сложным.

                                                                                                                                                                                                                                                                                              Он корректно обрабатывает ошибочные ситуации, а это главное.

                                                                                                                                                                                                                                                                                              Пример для вас я приведу позднее, а пока замечу, что "попеременная" работа с несколькими файлами и проблемы с обработкой ошибочных ситуаций при этом - проблемы проектирования приложения. Иными словами, вы сначала сами создаёте себе трудности, а потом мужественно их преодолеваете. И при таком подходе вас не спасёт игнорирование ошибок, возникающих при освобождении ресурсов. Эти ошибки _могут_ возникнуть, а значит их следует обрабатывать.

                                                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                                                              Плохо подобрал. С такими неправильными потоками - что с RAII, что без - проблем выше крыши.

                                                                                                                                                                                                                                                                                              Про неправильность потоков отдельно, плз. Что в них неправильного?
                                                                                                                                                                                                                                                                                              Сообщение отредактировано: wind -
                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                Там так и написано: "здесь нет защиты от ошибок, не связанных с вводом-выводом и штатного закрытия".

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

                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                В этом случае утечка невозможна.

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

                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                Он корректно обрабатывает ошибочные ситуации

                                                                                                                                                                                                                                                                                                Где? Добрую часть возможных ошибочных ситуаций он попросту игнорирует. Это и есть корректная обработка?

                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                Он корректно обрабатывает ошибочные ситуации, а это главное.

                                                                                                                                                                                                                                                                                                Т.е. подразумевается, что два архитектурных решения, позволяющих корректно обрабатывать ошибочные ситуации, не имеет смысла сравнивать? :huh:

                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                Иными словами, вы сначала сами создаёте себе трудности, а потом мужественно их преодолеваете.

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

                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                И при таком подходе вас не спасёт игнорирование ошибок, возникающих при освобождении ресурсов. Эти ошибки _могут_ возникнуть, а значит их следует обрабатывать.

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

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

                                                                                                                                                                                                                                                                                                В-третьих, я не вижу нормальной обработки исключений в приведённом выше куске кода на Java.

                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                Про неправильность потоков отдельно, плз. Что в них неправильного?

                                                                                                                                                                                                                                                                                                Внедрение небессбойных операций в функцию, инкапсулирующую в себе освобождение ресурсов. Как я уже сказал, это приводит к проблемам независимо от использования или неиспользования идиомы RAII.

                                                                                                                                                                                                                                                                                                Кстати, вопрос на засыпку. Можно ли в Java в блоке finally генерировать исключения, и если да, то как долго эти исключения могут существовать в необработанном виде?
                                                                                                                                                                                                                                                                                                  Dantes, вот, откопал для вас пример который вы хотели - работа с целой кучей файлов разом (это программка, которая разбивает некоторый лог по источникам сообщений):

                                                                                                                                                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                    import java.io.BufferedInputStream;
                                                                                                                                                                                                                                                                                                    import java.io.BufferedOutputStream;
                                                                                                                                                                                                                                                                                                    import java.io.DataInputStream;
                                                                                                                                                                                                                                                                                                    import java.io.DataOutputStream;
                                                                                                                                                                                                                                                                                                    import java.io.File;
                                                                                                                                                                                                                                                                                                    import java.io.FileInputStream;
                                                                                                                                                                                                                                                                                                    import java.io.FileOutputStream;
                                                                                                                                                                                                                                                                                                    import java.io.IOException;
                                                                                                                                                                                                                                                                                                    import java.util.HashMap;
                                                                                                                                                                                                                                                                                                    import java.util.Map;
                                                                                                                                                                                                                                                                                                    import java.util.concurrent.BlockingQueue;
                                                                                                                                                                                                                                                                                                    import java.util.concurrent.ExecutorService;
                                                                                                                                                                                                                                                                                                    import java.util.concurrent.Executors;
                                                                                                                                                                                                                                                                                                    import java.util.concurrent.LinkedBlockingQueue;
                                                                                                                                                                                                                                                                                                    import java.util.concurrent.atomic.AtomicBoolean;
                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                    public class Divisor {
                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                        static class LogEntry {
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            String type;
                                                                                                                                                                                                                                                                                                            String data;
                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                            public LogEntry(DataInputStream inputStream) throws IOException {
                                                                                                                                                                                                                                                                                                                type = inputStream.readUTF();
                                                                                                                                                                                                                                                                                                                data = inputStream.readUTF();
                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            public void saveTo(DataOutputStream outputStream) throws IOException {
                                                                                                                                                                                                                                                                                                                outputStream.writeUTF(type);
                                                                                                                                                                                                                                                                                                                outputStream.writeUTF(data);
                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                        static class LogWriter implements Runnable {
                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                            private String type;
                                                                                                                                                                                                                                                                                                            private BlockingQueue<LogEntry> entries;
                                                                                                                                                                                                                                                                                                            private AtomicBoolean stop;
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            public LogWriter(String type, BlockingQueue<LogEntry> entries, AtomicBoolean stop) {
                                                                                                                                                                                                                                                                                                                this.type = type;
                                                                                                                                                                                                                                                                                                                this.entries = entries;
                                                                                                                                                                                                                                                                                                                this.stop = stop;
                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                            public void run() {
                                                                                                                                                                                                                                                                                                                File file = new File(type + ".log");
                                                                                                                                                                                                                                                                                                                try {
                                                                                                                                                                                                                                                                                                                    FileOutputStream fileOutputStream =
                                                                                                                                                                                                                                                                                                                        new FileOutputStream(file);
                                                                                                                                                                                                                                                                                                                    try {
                                                                                                                                                                                                                                                                                                                        DataOutputStream dataOutputStream = new DataOutputStream(
                                                                                                                                                                                                                                                                                                                            new BufferedOutputStream(fileOutputStream));
                                                                                                                                                                                                                                                                                                                        while (entries.size() > 0 || !stop.get() && !Thread.interrupted()) {
                                                                                                                                                                                                                                                                                                                            try {
                                                                                                                                                                                                                                                                                                                                entries.take().saveTo(dataOutputStream);
                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                            catch (InterruptedException thrown) {
                                                                                                                                                                                                                                                                                                                                break;
                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                        dataOutputStream.flush();
                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                    finally {
                                                                                                                                                                                                                                                                                                                        fileOutputStream.close();
                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                catch (IOException thrown) {
                                                                                                                                                                                                                                                                                                                    System.out.printf("Error writing file %s\n", file);
                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                        public static void main(String... args) {
                                                                                                                                                                                                                                                                                                            if (args.length != 1) {
                                                                                                                                                                                                                                                                                                                System.out.printf("Usage: Divisor <filename>\n");
                                                                                                                                                                                                                                                                                                                return;
                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                            File file = new File(args[0]);
                                                                                                                                                                                                                                                                                                            try {
                                                                                                                                                                                                                                                                                                                DataInputStream dataInputStream = new DataInputStream(
                                                                                                                                                                                                                                                                                                                    new BufferedInputStream(
                                                                                                                                                                                                                                                                                                                        new FileInputStream(file)
                                                                                                                                                                                                                                                                                                                    ));
                                                                                                                                                                                                                                                                                                                try {
                                                                                                                                                                                                                                                                                                                    ExecutorService executor =
                                                                                                                                                                                                                                                                                                                        Executors.newCachedThreadPool();
                                                                                                                                                                                                                                                                                                                    try {
                                                                                                                                                                                                                                                                                                                        AtomicBoolean stop = new AtomicBoolean();
                                                                                                                                                                                                                                                                                                                        try {
                                                                                                                                                                                                                                                                                                                            Map<String, BlockingQueue<LogEntry>> queues =
                                                                                                                                                                                                                                                                                                                                new HashMap<String, BlockingQueue<LogEntry>>();
                                                                                                                                                                                                                                                                                                                            while (dataInputStream.available() > 0) {
                                                                                                                                                                                                                                                                                                                                LogEntry entry = new LogEntry(dataInputStream);
                                                                                                                                                                                                                                                                                                                                BlockingQueue<LogEntry> queue = queues.get(entry.type);
                                                                                                                                                                                                                                                                                                                                if (queue == null) {
                                                                                                                                                                                                                                                                                                                                    queues.put(
                                                                                                                                                                                                                                                                                                                                        entry.type,
                                                                                                                                                                                                                                                                                                                                        queue = new LinkedBlockingQueue<LogEntry>());
                                                                                                                                                                                                                                                                                                                                    executor.execute(
                                                                                                                                                                                                                                                                                                                                        new LogWriter(entry.type, queue, stop));
                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                queue.offer(entry);
                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                        finally {
                                                                                                                                                                                                                                                                                                                            stop.set(true);
                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                    catch (IOException thrown) {
                                                                                                                                                                                                                                                                                                                        System.out.printf("Error reading file %s\n", file);
                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                    executor.shutdown();
                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                finally {
                                                                                                                                                                                                                                                                                                                    dataInputStream.close();
                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                            catch (IOException thrown) {
                                                                                                                                                                                                                                                                                                                System.out.printf("Error opening file %s\n", file);
                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                    Цитата wind @
                                                                                                                                                                                                                                                                                                    Dantes, вот, откопал для вас пример который вы хотели - работа с целой кучей файлов разом (это программка, которая разбивает некоторый лог по источникам сообщений):

                                                                                                                                                                                                                                                                                                    Жесть...

                                                                                                                                                                                                                                                                                                    Вообще, тут все же нужно рассуждать здраво. Если разработчику необходим контроль ошибок при освобождении ресурсов - ему надо его предоставить. Но! Не надо при этом усложнять. Я почему чуть раньше говорил про проценты и т. д. В большинстве случаев достаточно того, что при вызове функции освобождения ресурса ресурс будет освобожден. На сколько успешно при этом будут выполнены сопутствующие операции - уже не так важно. В тех случаях, когда это критично - можно (и нужно) вызывать соответствующие функции явно и контролировать результат их работы.
                                                                                                                                                                                                                                                                                                    Я это к тому, что в подавляющем большинстве случаев техника освобождения ресурса в деструкторе без выбрасывания исключения оправдывает себя на все сто. В оставшихся случаях разработчиком будут применены специальные меры и средства контроля. Но не более того.
                                                                                                                                                                                                                                                                                                    Скажем так. Разработка бесзбойного софта - это отдельная песня, требующая особых подходов и методов, которые редкоприменимы в обычной жизни.
                                                                                                                                                                                                                                                                                                      Цитата Dantes @
                                                                                                                                                                                                                                                                                                      Здесь либо не хватает запятой, либо неправильно указаны падежи. Надо всё-таки соблюдать правила русского языка хотя бы в той мере, чтобы без труда можно было понять смысл написанного, не разгадывая ребусов.

                                                                                                                                                                                                                                                                                                      Прошу меня простить за запятую, но вы могли бы сначала уточнить, что я написал (если уж так непонятно), а потом отвечать ;)

                                                                                                                                                                                                                                                                                                      Цитата Dantes @
                                                                                                                                                                                                                                                                                                      Ну как же? Первый файл мы открыли, а при открытии второго сгенерировалось исключение. Кто будет закрывать первый файл?

                                                                                                                                                                                                                                                                                                      Где вы увидели второй файл? В этой строке создаётся буферизующий поток-обёртка.

                                                                                                                                                                                                                                                                                                      Цитата Dantes @
                                                                                                                                                                                                                                                                                                      Где? Добрую часть возможных ошибочных ситуаций он попросту игнорирует. Это и есть корректная обработка?

                                                                                                                                                                                                                                                                                                      Ох... Еще раз обращаю ваше внимание на первую мою реплику в сообщении #142. Тот кусочек кода показывает, что я могу сделать при возникновении ошибки во время закрытия файла.

                                                                                                                                                                                                                                                                                                      Цитата Dantes @
                                                                                                                                                                                                                                                                                                      Забавно слышать это от человека, который предлагает бросать исключения в функциях, инкапсулирующих в себе освобождение ресурсов, чего реально можно избежать, в отличие от необходимости одновременной работы с несколькими ресурсами.

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

                                                                                                                                                                                                                                                                                                      Цитата Dantes @
                                                                                                                                                                                                                                                                                                      Во-вторых, на случай, когда допускается неудачное завершение функции, инкапсулирующей в себе освобождение ресурсов, я уже преложил способ обработки исключитальной ситуации (правда, вместо функционального объекта в качестве обработчика лучше всё же передавать объект некоторого класса с переопределёнными виртуальными функциями - каждой такой функцией будет обрабатываться своя исключительная ситуация).

                                                                                                                                                                                                                                                                                                      Функция системного api, используемая при освобождении ресурса, может завершиться с ошибкой. Это означает, что у вас нет никаких причин считать вероятность ошибки нулевой. В особенности такой ошибки, от которой, повторюсь, зависит дальнейшая работа программы.

                                                                                                                                                                                                                                                                                                      Цитата Dantes @
                                                                                                                                                                                                                                                                                                      В-третьих, я не вижу нормальной обработки исключений в приведённом выше куске кода на Java.

                                                                                                                                                                                                                                                                                                      См. выше :wacko:

                                                                                                                                                                                                                                                                                                      Цитата Dantes @
                                                                                                                                                                                                                                                                                                      Внедрение небессбойных операций в функцию, инкапсулирующую в себе освобождение ресурсов.

                                                                                                                                                                                                                                                                                                      См. выше :wall:

                                                                                                                                                                                                                                                                                                      Цитата Dantes @
                                                                                                                                                                                                                                                                                                      Можно ли в Java в блоке finally генерировать исключения, и если да, то как долго эти исключения могут существовать в необработанном виде?

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


                                                                                                                                                                                                                                                                                                      Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                      В большинстве случаев достаточно того, что при вызове функции освобождения ресурса ресурс будет освобожден. На сколько успешно при этом будут выполнены сопутствующие операции - уже не так важно. В тех случаях, когда это критично - можно (и нужно) вызывать соответствующие функции явно и контролировать результат их работы.
                                                                                                                                                                                                                                                                                                      Я это к тому, что в подавляющем большинстве случаев техника освобождения ресурса в деструкторе без выбрасывания исключения оправдывает себя на все сто.

                                                                                                                                                                                                                                                                                                      Скажем так, столь трепетное отношение к возможным ошибкам, которое я тут демонстрирую, действительно не всегда себя оправдывает. Я могу просто написать try { ... } finally { ...close(); } и вполне успокоиться на том, что исключительная ситуация приведёт к немедленному завершению программы, а файл не останется открытым (правда, это может быть актуально только для *nix-систем). Но ведь если глотать ошибки, то может произойти чёрт знает что!

                                                                                                                                                                                                                                                                                                      Сейчас среди программеров стала наблюдаться какая-то особая боязнь исключений. Всё ошибки глотаются или оборачиваются в unchecked-исключения. Пользоваться софтом, написанным такими деятелями - сущая каторга.
                                                                                                                                                                                                                                                                                                      Сообщение отредактировано: wind -
                                                                                                                                                                                                                                                                                                        Так вот. При применении техники RAII предполагается (на этом предположении и основана техника), что деструктор, освобождающий ресурс, всегда бесзбойный. Всегда. А обо всех ошибки, которые могли произойти, должно быть оповещено до вызова деструктора. Основание для этого простое. Берем простой пример:

                                                                                                                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                          void foo()
                                                                                                                                                                                                                                                                                                          {
                                                                                                                                                                                                                                                                                                             try
                                                                                                                                                                                                                                                                                                             {
                                                                                                                                                                                                                                                                                                                std::ofstream out("out.txt");
                                                                                                                                                                                                                                                                                                                bar(out);
                                                                                                                                                                                                                                                                                                             } // 2
                                                                                                                                                                                                                                                                                                             catch (...)
                                                                                                                                                                                                                                                                                                             {
                                                                                                                                                                                                                                                                                                                 throw;
                                                                                                                                                                                                                                                                                                             }
                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                          void bar(std::ostream& out)
                                                                                                                                                                                                                                                                                                          {
                                                                                                                                                                                                                                                                                                             out.write(some_big_buf, buf_size);
                                                                                                                                                                                                                                                                                                             if (out.pcount() != buf_size())
                                                                                                                                                                                                                                                                                                                throw WriteError(); // 1
                                                                                                                                                                                                                                                                                                          }


                                                                                                                                                                                                                                                                                                        Предположим ситуацию. В файл пишется что-то большое. Записаться не может, о чем в точке 1 кидается соответствующая ошибка. Когда поток выполнения доходит до точки 2 у потока (в деструкторе) вызывается метод close(), который также кидает свое исключение (не могу сбросить буферы файла на винт). Но одно исключение уже "летит". Что делать со вторым? Ну хорошо, перепишем код так:

                                                                                                                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                          void foo()
                                                                                                                                                                                                                                                                                                          {
                                                                                                                                                                                                                                                                                                             std::ofstream out("out.txt");
                                                                                                                                                                                                                                                                                                             try
                                                                                                                                                                                                                                                                                                             {
                                                                                                                                                                                                                                                                                                                bar(out);
                                                                                                                                                                                                                                                                                                             }
                                                                                                                                                                                                                                                                                                             catch (...)
                                                                                                                                                                                                                                                                                                             {
                                                                                                                                                                                                                                                                                                                 try
                                                                                                                                                                                                                                                                                                                 {
                                                                                                                                                                                                                                                                                                                    out.close(); // 2
                                                                                                                                                                                                                                                                                                                 }
                                                                                                                                                                                                                                                                                                                 catch (...)
                                                                                                                                                                                                                                                                                                                 {
                                                                                                                                                                                                                                                                                                                     ??? // 3
                                                                                                                                                                                                                                                                                                                 }
                                                                                                                                                                                                                                                                                                                 throw;
                                                                                                                                                                                                                                                                                                             }
                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                          void bar(std::ostream& out)
                                                                                                                                                                                                                                                                                                          {
                                                                                                                                                                                                                                                                                                             out.write(some_big_buf, buf_size);
                                                                                                                                                                                                                                                                                                             if (out.pcount() != buf_size())
                                                                                                                                                                                                                                                                                                                throw WriteError(); // 1
                                                                                                                                                                                                                                                                                                          }


                                                                                                                                                                                                                                                                                                        В точке 1 кидается исключение, оно долетает до функции foo, переходит в обработчик, там (в точке 2) вызывается метод close() (освобождаем ресурсы), кидается другое исключение, которое ловится в точке 3. Теперь внимание - вопрос. Оба исключения должны быть обработаны вызывающей стороной. Какие должны быть действия разработчика и runtime-среды? Как оповестить вызывающую сторону об обоих возникших исключениях?
                                                                                                                                                                                                                                                                                                          Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                          Какие должны быть действия разработчика и runtime-среды? Как оповестить вызывающую сторону об обоих возникших исключениях?

                                                                                                                                                                                                                                                                                                          Flex Ferrum, вы хотите разъяснить мне, что такое RAII и почему деструктор не должен выбрасывать исключения? Я это и так прекрасно понимаю, потому и говорю, что такой подход не всегда применим.

                                                                                                                                                                                                                                                                                                          Кстати, мне, уже давно отошедшему от c++ уже даже трудно понять, как вообще может быть порождено более одного необработанного исключения. В java такого просто не может быть 8-)
                                                                                                                                                                                                                                                                                                          Сообщение отредактировано: wind -
                                                                                                                                                                                                                                                                                                            Цитата wind @
                                                                                                                                                                                                                                                                                                            Я это и так прекрасно понимаю, потому и говорю, что такой подход не всегда применим.

                                                                                                                                                                                                                                                                                                            Так никто и не говорит, что он всегда применим. Но в большинстве случаев - очень даже.
                                                                                                                                                                                                                                                                                                              Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                              Так никто и не говорит, что он всегда применим.

                                                                                                                                                                                                                                                                                                              А вот тут мы возвращаемся к началу этого спора. Кое-кто высказался насчёт несовершенства сборщика мусора - дескать, должен еще и ресурсы подбирать. А вот не получается. Предоставлять оба способа управления - ручной и автоматический бессмысленно - мы получим все недостатки обоих подходов и ни одного их преимущества. Следовательно, для создания такого универсального сборщика следует внедрить все операции с ресурсами в язык. И что это получится за уродец?
                                                                                                                                                                                                                                                                                                                Ох, wind, я бы тебе рассказал, как мы в свое время прикручивали java к одной промышленной серверной системе. И куда там в итоге был отправлен сборщик мусора. И как ломало java-программера от необходимости явно релизить объекты, имеющие реализацию на jni... Вообщем, любовь была еще та... При этом на плюсах те же самые задачи (с этим самым RAII) решались на "раз-два".

                                                                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                                                                Это не смотря на то, что, вообще говоря, объекты успешно поддавались финализации. Но было одно маленькое "НО". Когда gc (при работе системы под большой нагрузкой) доходил до разгребания мусора, памяти отжиралось под гигабайт (практически вся доступная), и на работу gc уже не хватало системных ресурсов... Вообщем, было весело...
                                                                                                                                                                                                                                                                                                                  Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                  Ох, wind, я бы тебе рассказал, как мы в свое время прикручивали java к одной промышленной серверной системе.

                                                                                                                                                                                                                                                                                                                  Ну что ж, я потрясён до глубины души :D Видимо, вам попался очень дурной java-программер.
                                                                                                                                                                                                                                                                                                                    Цитата wind @
                                                                                                                                                                                                                                                                                                                    Видимо, вам попался очень дурной java-программер.

                                                                                                                                                                                                                                                                                                                    Да нет. Программер был хороший. А вот задачка - весьма специфическая. Надо было написать java-фронтэнд к набору COM-объектов, реализованных на плюсах. Просто ситуация осложнялась тем, что этих COM-объектов в процесс работы должно было создаваться ну очень много. И если их вовремя не освобождать, то память достаточно быстро забивалась. В данном случае "вовремя" - это сразу, когда объект перестает быть нужным. А не когда это сочтет нужным сделать gc.
                                                                                                                                                                                                                                                                                                                      Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                      Да нет. Программер был хороший. А вот задачка - весьма специфическая. Надо было написать java-фронтэнд к набору COM-объектов, реализованных на плюсах. Просто ситуация осложнялась тем, что этих COM-объектов в процесс работы должно было создаваться ну очень много. И если их вовремя не освобождать, то память достаточно быстро забивалась. В данном случае "вовремя" - это сразу, когда объект перестает быть нужным. А не когда это сочтет нужным сделать gc.

                                                                                                                                                                                                                                                                                                                      Нет, не хороший. Это я вам как краевед говорю. Только полный идиот, извините, будет привязывать высвобождение ресурса, создаваемого не на всё время жизни программы к жизненному циклу GC. Это азы, мало даже касающиеся java. <вымарал, а то заклюют за эккелененавистничество>

                                                                                                                                                                                                                                                                                                                      Если вы присмотритесь к более ранним сообщениям, вы увидите моё (единственно верное, как я полагаю) мнение на этот счёт. GC тут совершенно не при чём, просто за его счёт софтина не подыхает сразу, а продолжает корчится в агонии.
                                                                                                                                                                                                                                                                                                                      Сообщение отредактировано: wind -
                                                                                                                                                                                                                                                                                                                        Цитата wind @
                                                                                                                                                                                                                                                                                                                        Нет, не хороший. Это я вам как краевед говорю.

                                                                                                                                                                                                                                                                                                                        И какое бы ты предложил решение этой задачки?
                                                                                                                                                                                                                                                                                                                          Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                          И какое бы ты предложил решение этой задачки?

                                                                                                                                                                                                                                                                                                                          Только ручное высвобождение ресурсов. Работа с JNI накладывает некоторые ограничения на права и свободы java-программера, это очевидно и естественно.
                                                                                                                                                                                                                                                                                                                            Цитата wind
                                                                                                                                                                                                                                                                                                                            Dantes, вот, откопал для вас пример который вы хотели - работа с целой кучей файлов разом

                                                                                                                                                                                                                                                                                                                            И вот это нагромождение try блоков (в котором мне, честно говоря, даже не хочется разбираться) можно считать примером разумного использования встроенного механизма обработки исключений? :wacko:

                                                                                                                                                                                                                                                                                                                            Цитата wind
                                                                                                                                                                                                                                                                                                                            Функция системного api, используемая при освобождении ресурса, может завершиться с ошибкой.

                                                                                                                                                                                                                                                                                                                            Это при наличии-то ресурса? Ну, кривое API - уто уже серьёзно.

                                                                                                                                                                                                                                                                                                                            Цитата wind
                                                                                                                                                                                                                                                                                                                            Про неправильность потоков отдельно, плз. Что в них неправильного?

                                                                                                                                                                                                                                                                                                                            Цитата Dantes
                                                                                                                                                                                                                                                                                                                            Внедрение небессбойных операций в функцию, инкапсулирующую в себе освобождение ресурсов.

                                                                                                                                                                                                                                                                                                                            Цитата wind
                                                                                                                                                                                                                                                                                                                            См. выше

                                                                                                                                                                                                                                                                                                                            Есть и ещё одна неправильность: генерирование исключений в таких функциях (по крайней мере, без проверки наличия неперехваченного исключения - в Java ведь, наверно, есть аналог функции uncaught_exception() из C++, позволяющей узнавать о наличии неперехваченного исключения?)

                                                                                                                                                                                                                                                                                                                            Цитата wind
                                                                                                                                                                                                                                                                                                                            Можно. Необработанные исключения передаются уровенем выше, если уровнем выше никто их не обрабатывает - поток завершается.

                                                                                                                                                                                                                                                                                                                            Цитата wind
                                                                                                                                                                                                                                                                                                                            Кстати, мне, уже давно отошедшему от c++ уже даже трудно понять, как вообще может быть порождено более одного необработанного исключения. В java такого просто не может быть

                                                                                                                                                                                                                                                                                                                            А что происходит, когда в момент генерирования исключения в finally-блоке одно необработанное исключение уже есть? Terminate? Или terminate наступает, когда второе исключение покидает finally-блок? Или что-то ещё?

                                                                                                                                                                                                                                                                                                                            Цитата wind
                                                                                                                                                                                                                                                                                                                            Flex Ferrum, вы хотите разъяснить мне, что такое RAII и почему деструктор не должен выбрасывать исключения? Я это и так прекрасно понимаю, потому и говорю, что такой подход не всегда применим.

                                                                                                                                                                                                                                                                                                                            Какой подход - RAII или сообщение об ошибках в функциях, освобождающих ресурсы, при помощи выброса исключений?
                                                                                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                                                                                              И вот это нагромождение try блоков (в котором мне, честно говоря, даже не хочется разбираться) можно считать примером разумного использования встроенного механизма обработки исключений?

                                                                                                                                                                                                                                                                                                                              Да, это единственно верный способ использования механизма исключений в java. В любой нештатной (не предусмотренной) ситуации выбрасывается исключение. Возврат методом управления в вызывающий код подразумевает его штатное завешение. Именно для этого и были придуманы исключения.

                                                                                                                                                                                                                                                                                                                              По существу вы можете что-нибудь сказать? Или, может быть, вы знаете способ обработать исключение без try ... catch? И заодно объясните мне, зачем я искал этот пример, если вам "не хочется" в нём разбираться?

                                                                                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                                                                                              Это при наличии-то ресурса? Ну, кривое API - уто уже серьёзно.

                                                                                                                                                                                                                                                                                                                              Вы что хотели сказать? Не пользоваться, например, winapi, если не нравится? Это как-с?

                                                                                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                                                                                              Внедрение небессбойных операций в функцию, инкапсулирующую в себе освобождение ресурсов.

                                                                                                                                                                                                                                                                                                                              Еще раз для танкистов: сама по себе операция освобождения ресурса не является и не может являться бессбойной. Вот если бы метод close() стандартного потока не порождал бы никаких исключений - это действительно было бы неправильным.

                                                                                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                                                                                              Есть и ещё одна неправильность: генерирование исключений в таких функциях (по крайней мере, без проверки наличия неперехваченного исключения - в Java ведь, наверно, есть аналог функции uncaught_exception() из C++, позволяющей узнавать о наличии неперехваченного исключения?)

                                                                                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                                                                                              А что происходит, когда в момент генерирования исключения в finally-блоке одно необработанное исключение уже есть? Terminate? Или terminate наступает, когда второе исключение покидает finally-блок? Или что-то ещё?

                                                                                                                                                                                                                                                                                                                              Dantes, читайте внимательно, пожалуйста. В java не может быть более одного необработанного исключения. Иными словами, если выполняется код throw ..., то нет и не может быть никаких необработанных исключений.

                                                                                                                                                                                                                                                                                                                              Цитата Dantes @
                                                                                                                                                                                                                                                                                                                              Какой подход - RAII или сообщение об ошибках в функциях, освобождающих ресурсы, при помощи выброса исключений?

                                                                                                                                                                                                                                                                                                                              RAII, реализованный на C++.
                                                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                                                Да, это единственно верный способ использования механизма исключений в java.

                                                                                                                                                                                                                                                                                                                                Ой, как я вам не завидую.

                                                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                                                В любой нештатной (не предусмотренной) ситуации выбрасывается исключение. Возврат методом управления в вызывающий код подразумевает его штатное завешение. Именно для этого и были придуманы исключения.

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

                                                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                                                По существу вы можете что-нибудь сказать? Или, может быть, вы знаете способ обработать исключение без try ... catch?

                                                                                                                                                                                                                                                                                                                                С RAII обычно нет надобности вкладывать try-блоки друг в друга - хватает и одного.

                                                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                                                И заодно объясните мне, зачем я искал этот пример, если вам "не хочется" в нём разбираться?

                                                                                                                                                                                                                                                                                                                                И правда - зачем? Ведь случись какое-то исключение в finally после неудачного исполнения try - будет terminate. Эффект тот же, что и с деструкторами C++, только в C++ всё это можно записать гораздо проще и нагляднее, используя RAII. К чему, спрашивается, тогда было затевать эти разговоры про исключения в деструкторах и убогость RAII?

                                                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                                                Вы что хотели сказать? Не пользоваться, например, winapi, если не нравится? Это как-с?

                                                                                                                                                                                                                                                                                                                                Но ведь API не кидает исключений при неудачном закрытии ресурса, так-с?

                                                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                                                Вот если бы метод close() стандартного потока не порождал бы никаких исключений - это действительно было бы неправильным.

                                                                                                                                                                                                                                                                                                                                Почему? Чем генерация исключений в данном случае предпочтительней альтернативных способов сообщения об ошибке?

                                                                                                                                                                                                                                                                                                                                Цитата wind
                                                                                                                                                                                                                                                                                                                                Dantes, читайте внимательно, пожалуйста. В java не может быть более одного необработанного исключения.

                                                                                                                                                                                                                                                                                                                                Ну, не может и ладно. Я просто хотел уточнить на всякий случай.
                                                                                                                                                                                                                                                                                                                                  Цитата wind @
                                                                                                                                                                                                                                                                                                                                  В java не может быть более одного необработанного исключения.

                                                                                                                                                                                                                                                                                                                                  Тогда как разрешить ситуацию, когда исключение, сгенерированное в методе close (в catch-обработчике) должно быть также обработано в вызывающем коде? Тут реально возникает ситуация, когда вызывающий код должен получить и обработать сразу два исключения:
                                                                                                                                                                                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                    void foo()
                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                       std::ofstream out("out.txt");
                                                                                                                                                                                                                                                                                                                                       try
                                                                                                                                                                                                                                                                                                                                       {
                                                                                                                                                                                                                                                                                                                                          bar(out);
                                                                                                                                                                                                                                                                                                                                       }
                                                                                                                                                                                                                                                                                                                                       catch (...)
                                                                                                                                                                                                                                                                                                                                       {
                                                                                                                                                                                                                                                                                                                                           try
                                                                                                                                                                                                                                                                                                                                           {
                                                                                                                                                                                                                                                                                                                                              out.close(); // 2
                                                                                                                                                                                                                                                                                                                                           }
                                                                                                                                                                                                                                                                                                                                           catch (...)
                                                                                                                                                                                                                                                                                                                                           {
                                                                                                                                                                                                                                                                                                                                               ??? // 3 Здесь мы не можем адекватно обработать исключение, сгенерированное в точке 2. Нужно его отдавать вызывающему коду
                                                                                                                                                                                                                                                                                                                                           }
                                                                                                                                                                                                                                                                                                                                           throw;
                                                                                                                                                                                                                                                                                                                                       }
                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                    void bar(std::ostream& out)
                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                       out.write(some_big_buf, buf_size);
                                                                                                                                                                                                                                                                                                                                       if (out.pcount() != buf_size())
                                                                                                                                                                                                                                                                                                                                          throw WriteError(); // 1 - сгенерировали исключение, которое может быть адекватно обработано только в точке 4
                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                    void xxx()
                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                       try
                                                                                                                                                                                                                                                                                                                                       {
                                                                                                                                                                                                                                                                                                                                          foo();
                                                                                                                                                                                                                                                                                                                                       }
                                                                                                                                                                                                                                                                                                                                       catch (...) // 4
                                                                                                                                                                                                                                                                                                                                       {
                                                                                                                                                                                                                                                                                                                                       }
                                                                                                                                                                                                                                                                                                                                    }

                                                                                                                                                                                                                                                                                                                                  Впрочем, я об этом уже спрашивал. Как должен вести себя рантайм, чтобы выполнить желание программиста, обозначенное в точках 1 и 3?
                                                                                                                                                                                                                                                                                                                                    Цитата Dantes @
                                                                                                                                                                                                                                                                                                                                    Ой, как я вам не завидую.

                                                                                                                                                                                                                                                                                                                                    :lool:

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

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

                                                                                                                                                                                                                                                                                                                                    Цитата Dantes @
                                                                                                                                                                                                                                                                                                                                    С RAII обычно нет надобности вкладывать try-блоки друг в друга - хватает и одного.

                                                                                                                                                                                                                                                                                                                                    Ага, и что он там обработает и зачем - да шут его знает. В лог напишет :lol:

                                                                                                                                                                                                                                                                                                                                    Цитата Dantes @
                                                                                                                                                                                                                                                                                                                                    Но ведь API не кидает исключений при неудачном закрытии ресурса, так-с?

                                                                                                                                                                                                                                                                                                                                    Нет, не так-с. CloseHandle может завершиться с ошибкой.

                                                                                                                                                                                                                                                                                                                                    Цитата Dantes @
                                                                                                                                                                                                                                                                                                                                    Почему? Чем генерация исключений в данном случае предпочтительней альтернативных способов сообщения об ошибке?

                                                                                                                                                                                                                                                                                                                                    Нет никакой ложки, Dantes ;) Любой другой способ сигнализации позволит программе спокойно выполняться дальше. Если программист, использующий данный класс, не вспомнит о возможности обработать ошибочную ситуацию, то всё будет шито-крыто до тех пор, пока ошибка не всплывёт уже во время экплуатации приложения.

                                                                                                                                                                                                                                                                                                                                    Цитата Dantes @
                                                                                                                                                                                                                                                                                                                                    К чему, спрашивается, тогда было затевать эти разговоры про исключения в деструкторах и убогость RAII?

                                                                                                                                                                                                                                                                                                                                    См. выше :wall:

                                                                                                                                                                                                                                                                                                                                    Цитата Dantes @
                                                                                                                                                                                                                                                                                                                                    И правда - зачем?

                                                                                                                                                                                                                                                                                                                                    И действительно <_<
                                                                                                                                                                                                                                                                                                                                    Dantes, пожалуй, вы мне более не интересны в качестве собеседника. К тому же у вас давно закончились аргументы.

                                                                                                                                                                                                                                                                                                                                    Добавлено
                                                                                                                                                                                                                                                                                                                                    Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                    Тогда как разрешить ситуацию, когда исключение, сгенерированное в методе close (в catch-обработчике) должно быть также обработано в вызывающем коде?

                                                                                                                                                                                                                                                                                                                                    Если я поймал исключение с помощью catch, значит я уже знаю как его обработать здесь и сейчас. Если же нет - отдаю вызвавшему коду (не ловлю) или порождаю новое исключение.
                                                                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                                                                      Если я поймал исключение с помощью catch, значит я уже знаю как его обработать здесь и сейчас

                                                                                                                                                                                                                                                                                                                                      Совсем не обязательно. Ты можешь поймать исключение для того, чтобы преобразовать его в другое исключение.
                                                                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                                                                      Если же нет - отдаю вызвавшему коду (не ловлю) или порождаю новое исключение.

                                                                                                                                                                                                                                                                                                                                      Так вот в том то и фишка - в ситуации, когда ты должен породить новое исключение в процессе обработки другого исключения. Как поступать? На какое из исключений "забить"?
                                                                                                                                                                                                                                                                                                                                        Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                        Ты можешь поймать исключение для того, чтобы преобразовать его в другое исключение.

                                                                                                                                                                                                                                                                                                                                        Это и есть обработка :)

                                                                                                                                                                                                                                                                                                                                        Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                        На какое из исключений "забить"?

                                                                                                                                                                                                                                                                                                                                        Выбирать. В вашем примере вызывающему коду нет надобности поймать оба типа исключения, в любом случае запись файла обломилась. Значит я могу выбросить какой-нибудь FileCreateException с нужным сообщением. Если же мне факт незакрытия файла кажется важнее, то, например, FatalIOError. А еще я могу сделать так:

                                                                                                                                                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                          throw new MyBusinessException("Cannot create file", causedByException);

                                                                                                                                                                                                                                                                                                                                        т. е. передать цепочку исключений.
                                                                                                                                                                                                                                                                                                                                        Сообщение отредактировано: wind -
                                                                                                                                                                                                                                                                                                                                          Цитата wind @
                                                                                                                                                                                                                                                                                                                                          В вашем примере вызывающему коду нет надобности поймать оба типа исключения, в любом случае запись файла обломилась. Значит я могу выбросить какой-нить FileCreateException с нужным сообщением.

                                                                                                                                                                                                                                                                                                                                          Гм. Ой ли? Первое исключение может, например, сигнализировать о том, что в процессе работы функции bar не удалось преобразовать тип (некорректные входные данные). В процессе его обработки (в финализации в foo) выясняется, что мы еще и файл закрыть не можем. Какое исключение откидываем, а какое оставляем жить?

                                                                                                                                                                                                                                                                                                                                          Добавлено
                                                                                                                                                                                                                                                                                                                                          Цитата wind @
                                                                                                                                                                                                                                                                                                                                          т. е. передать цепочку исключений.

                                                                                                                                                                                                                                                                                                                                          Угумс. После чего обработка исключений из простого механизма-помошника быстро превращается в ад в попытках уследить за всеми возможными ошибками и их комбинациями... Так ведь получается... Или ты можешь предложить простой способ обработки цепочки из двух-трех-четырех исключений? А если еще учитывать, что в момент создания объекта исключения тоже может произойти исключение... Ведь может? Как предлагаешь действовать в такой ситуации? Или все же остановимся на том, что ряд операций должны быть безсбойными....
                                                                                                                                                                                                                                                                                                                                            Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                            Гм. Ой ли? Первое исключение может, например, сигнализировать о том, что в процессе работы функции bar не удалось преобразовать тип (некорректные входные данные). В процессе его обработки (в финализации в foo) выясняется, что мы еще и файл закрыть не можем. Какое исключение откидываем, а какое оставляем жить?

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

                                                                                                                                                                                                                                                                                                                                            Добавлено
                                                                                                                                                                                                                                                                                                                                            Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                            После чего обработка исключений из простого механизма-помошника быстро превращается в ад в попытках уследить за всеми возможными ошибками и их комбинациями...

                                                                                                                                                                                                                                                                                                                                            С чего бы это? Ведь меня интересуют только определённые типы исключений, а не их комбинации. В любом случае это лучше, чем необходимость суметь поймать N исключений, где величина N не ограничена.

                                                                                                                                                                                                                                                                                                                                            Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                            А если еще учитывать, что в момент создания объекта исключения тоже может произойти исключение... Ведь может?

                                                                                                                                                                                                                                                                                                                                            Может. Но в любом случае, исключение будет только одно.
                                                                                                                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                                                                                                                              Ведь меня интересуют только определённые типы исключений, остальные я не смогу обработать и они уйдут выше. В любом случае это лучше, чем необходимость суметь поймать N исключений, где величина N не ограничена.

                                                                                                                                                                                                                                                                                                                                              Ну а как быть с ситуацией, когда к тебе прилетает некое BusinessException, в недрах которого сидит именно то causedException, которое тебя интересует. Но! На само BusinessException ты в данном фрагменте кода не реагируешь. Как разруливать такую ситуацию?
                                                                                                                                                                                                                                                                                                                                                Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                На само BusinessException ты в данном фрагменте кода не реагируешь. Как разруливать такую ситуацию?

                                                                                                                                                                                                                                                                                                                                                Как это не реагирую? Ведь именно его я и ловлю! Просто мне может быть важно / не важно продолжение цепочки.
                                                                                                                                                                                                                                                                                                                                                  Это я, кстати, не упомянул о том, что, фактически, код каждой функции тебя надо оборачивать в try-finally. Иначе освобождение ресурсов в момент пролета исключения происходить не будет. Так ведь?

                                                                                                                                                                                                                                                                                                                                                  Добавлено
                                                                                                                                                                                                                                                                                                                                                  Цитата wind @
                                                                                                                                                                                                                                                                                                                                                  Как это не реагирую? Ведь именно я и ловлю! Просто мне может быть важно / не важно продолжение цепочки.

                                                                                                                                                                                                                                                                                                                                                  Т. е. по сути, в каждой точке catch ты должен ловить "любое" исключение и разбирать - что же там у него внутрях. Так получается?
                                                                                                                                                                                                                                                                                                                                                    Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                    Это я, кстати, не упомянул о том, что, фактически, код каждой функции тебя надо оборачивать в try-finally.

                                                                                                                                                                                                                                                                                                                                                    Вроде того.
                                                                                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                                                                                      Вроде того.

                                                                                                                                                                                                                                                                                                                                                      А вот RAII от этого свободен. Я не обязан перегружать код лишними конструкциями, если в них нет реальной необходимости, и использую блоки try/catch только там, где действительно собираюсь обрабатывать исключения.
                                                                                                                                                                                                                                                                                                                                                        Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                        Т. е. по сути, в каждой точке catch ты должен ловить "любое" исключение и разбирать - что же там у него внутрях. Так получается?

                                                                                                                                                                                                                                                                                                                                                        Если это важно в данном методе - да. Но я, скорее всего поступлю более правильно: создам иерархию исключений и реагировать буду на интересующие меня либо на родителя, если причина меня не интересует.
                                                                                                                                                                                                                                                                                                                                                          Цитата wind @
                                                                                                                                                                                                                                                                                                                                                          Но я, скорее всего поступлю более правильно: создам иерархию исключений и реагировать буду на интересующие меня либо на родителя, если причина меня не интересует.

                                                                                                                                                                                                                                                                                                                                                          Я акцентировал внимание на ситуации, когда интересующее тебя исключение агрегировано в другое исключение, которое тебя, фактически, не интересует.
                                                                                                                                                                                                                                                                                                                                                            Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                            А вот RAII от этого свободен.

                                                                                                                                                                                                                                                                                                                                                            RAII не то чтобы свободен "от этого", он освбождает меня от возможности реагировать нужным образом на те или иные ошибки. Разве что каким-нибудь извращённым способом, когда обработку мне придётся помещать в другой класс/метод (и при этом код, зависящий от результата выполнения метода продолжит выполнятся, что совершенно недопустимо).
                                                                                                                                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                                                                                                                                              RAII не то чтобы свободен, он освбождает меня от возможности реагировать нужным образом на те или иные ошибки.

                                                                                                                                                                                                                                                                                                                                                              Не правильный вывод. Собственно, не совсем понятно - почему именно такой вывод ты сделал. При необходимости (реальной необходимости) такую возможность несложно обеспечить. В связке с RAII.

                                                                                                                                                                                                                                                                                                                                                              Добавлено
                                                                                                                                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                                                                                                                                              Разве что каким-нибудь извращённым способом, когда обработку мне придётся помещать в другой класс/метод.

                                                                                                                                                                                                                                                                                                                                                              Но твои методы не менее извращенные, согласись. Когда метод распухает и в глазах пестрит от try/catch/finaly - это не есть гуд. За логикой обработки ошибок теряется бизнес логика. Это, по твоему, нормальный подход?
                                                                                                                                                                                                                                                                                                                                                                Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                Но твои методы не менее извращенные, согласись. Когда метод распухает и в глазах пестрит от try/catch/finaly - это не есть гуд.
                                                                                                                                                                                                                                                                                                                                                                За логикой обработки ошибок теряется бизнес логика. Это, по твоему, нормальный подход?

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

                                                                                                                                                                                                                                                                                                                                                                Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                За логикой обработки ошибок теряется бизнес логика. Это, по твоему, нормальный подход?

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

                                                                                                                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                                                                                                                Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                Не правильный вывод. Собственно, не совсем понятно - почему именно такой вывод ты сделал. При необходимости (реальной необходимости) такую возможность несложно обеспечить.

                                                                                                                                                                                                                                                                                                                                                                Приведите, пожалуйста, пример. Только с учётом пары условий:
                                                                                                                                                                                                                                                                                                                                                                - коды ошибок/состояния - неприемлемый подход;
                                                                                                                                                                                                                                                                                                                                                                - обработка ошибки в том же методе, где вызывается опасный код.
                                                                                                                                                                                                                                                                                                                                                                  Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                  Я не понимаю людей, стремящихся к краткости кода в ущерб понятности и функциональности

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

                                                                                                                                                                                                                                                                                                                                                                  Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                  А разве логика обработки ошибок не есть часть бизнес-логики?

                                                                                                                                                                                                                                                                                                                                                                  А всегда ли она является таковой? Особенно, если в данном конкретном месте требуется преобразовывать одно исключение к другому, обертывать, обеспечивать корректный cleanup при пролете исключения и т. д. и т. п.

                                                                                                                                                                                                                                                                                                                                                                  Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                  Да и как можно потеряться в знакомых языковых конструкциях - наверное, нужно не знать языка?

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


                                                                                                                                                                                                                                                                                                                                                                  Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                  Приведите, пожалуйста, пример. Только с учётом пары условий:
                                                                                                                                                                                                                                                                                                                                                                  - коды ошибок/состояния - неприемлемый подход;
                                                                                                                                                                                                                                                                                                                                                                  - обработка ошибки в том же методе, где вызывается опасный код;

                                                                                                                                                                                                                                                                                                                                                                  К чему такие условия? Я сделаю так, как мне это будет удобным. Я не считаю, что исключения - единственный способ сообщения об ошибках. Как выясняется, исключения могут (в ряде случаев) усложнить, а не упросить код.
                                                                                                                                                                                                                                                                                                                                                                    Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                    К чему такие условия? Я сделаю так, как мне это будет удобным. Я не считаю, что исключения - единственный способ сообщения об ошибках. Как выясняется, исключения могут (в ряде случаев) усложнить, а не упросить код.

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

                                                                                                                                                                                                                                                                                                                                                                    А невыполнение вышеописанных условий как раз значительно усложняет код (по сравнению с парой лишних строк, делающих суть происходящего только понятнее). Кроме того, неиспользование исключений усложняет диагностику ошибки и только добавляет лишних трудов при написании механизмов, заменяющих имеющиеся (например, придётся как-то самому выуживать стек вызовов). Если говорить о пользователях моего класса/метода, то тут еще хуже: во-первых, придётся отдельно документировать мой способ сигнализации об ошибке, во-вторых, он со стопроцентной вероятностью будет проигнорирован.
                                                                                                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                      А невыполнение вышеописанных условий как раз значительно усложняет код (по сравнению с парой лишних строк, делающих суть происходящего только понятнее).

                                                                                                                                                                                                                                                                                                                                                                      Парой лишних строк? :) Это когда весь код пестрит try/catch/finally - это пара лишних строк? Это когда в код надо везде вставлять try/finally - это пара лишних строк? :)

                                                                                                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                      Кроме того, неиспользование исключений усложняет диагностику ошибки и только добавляет лишних трудов при написании механизмов, заменяющих имеющиеся (например, придётся как-то самому выуживать стек вызовов).

                                                                                                                                                                                                                                                                                                                                                                      Ошибки бывают разными, и диагностировать их можно (и нужно) по-разному. Исключение - один из таких механизмов. Но не единственно верный и не единственно возможный. Мы тут уже обсудили проблему двойных/тройных исключений. Элегантности в их обработке мало.


                                                                                                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                      Если говорить о пользователях моего класса/метода, то тут еще хуже

                                                                                                                                                                                                                                                                                                                                                                      Мы говорим сейчас не о внешнем интерфейсе твоего класса/метода, а о его реализации.
                                                                                                                                                                                                                                                                                                                                                                        Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                        Но не единственно верный и не единственно возможный.

                                                                                                                                                                                                                                                                                                                                                                        Так можно пример всё же привести? Если, конечно, это не те самые способы, которые я описал ранее?

                                                                                                                                                                                                                                                                                                                                                                        Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                        Мы тут уже обсудили проблему двойных/тройных исключений. Элегантности в их обработке мало.

                                                                                                                                                                                                                                                                                                                                                                        На самом деле такой проблемы не существует (по крайней мере, в java). Если венуться к примеру с неудачным закрытием файла, то вызывающий код не интересует причина неудачи, важен лишь факт и некоторая информация, которую можно сообщить пользователю. Нет никаких двойных/тройных исключений. Просто есть ошибки, предусмотренные программой и не предусмотренные. Например, исключение, выбрасываемое при конструировании другого исключения - это отличный повод вообще немедленно прервать выполнение программы соорудить багрепорт.
                                                                                                                                                                                                                                                                                                                                                                          Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                          Если венуться к примеру с неудачным закрытием файла, то вызывающий код не интересует причина неудачи, важен лишь факт и некоторая информация, которую можно сообщить пользователю.

                                                                                                                                                                                                                                                                                                                                                                          Еще раз внимательно прочитай мои посты. Прохождение одного исключения может вызывать возникновение другого (неудачное преобразование данных вызывает неудачу при закрытии файла - исключения логически не связанные). О чем надо сообщить пользователю? О том, что у него ошибка в исходных данных или о том, что на диске место кончилось? А если это библиотечная функция и вообще ничего не знает о том - как и кому сообщать?
                                                                                                                                                                                                                                                                                                                                                                            Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                            О чем надо сообщить пользователю? О том, что у него ошибка в исходных данных или о том, что на диске место кончилось? А если это библиотечная функция и вообще ничего не знает о том - как и кому сообщать?

                                                                                                                                                                                                                                                                                                                                                                            Есть объект - исключение. В числе прочего он содержит и сообщение об ошибке. А ещё может содержать метод для отображения этого сообщения. И еще много чего может содержать и уметь.
                                                                                                                                                                                                                                                                                                                                                                              Ну а пример я бы предложил такой:
                                                                                                                                                                                                                                                                                                                                                                              ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                class SuccessMontior
                                                                                                                                                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                                                                                                                                                public:
                                                                                                                                                                                                                                                                                                                                                                                    SuccessMontior(std::ofstream* f, bool& closeSuccess) : m_File(f), m_CloseSucceeded(closeSuccess) {;}
                                                                                                                                                                                                                                                                                                                                                                                    ~SuccessMontior()
                                                                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                                                                        m_File->close();
                                                                                                                                                                                                                                                                                                                                                                                        m_CloseSucceeded = m_File->fail();
                                                                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                private:
                                                                                                                                                                                                                                                                                                                                                                                    std::ofstream* m_File;
                                                                                                                                                                                                                                                                                                                                                                                    bool& m_CloseSucceeded;
                                                                                                                                                                                                                                                                                                                                                                                };
                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                void EmulateException(std::ostream& s)
                                                                                                                                                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                                                                                                                                                    std::vector<int> v(1, 1);
                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                    s << v.at(3) << std::endl;
                                                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                void FileOp(const char* fileName)
                                                                                                                                                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                                                                                                                                                    bool file_op_ok = false;
                                                                                                                                                                                                                                                                                                                                                                                    try
                                                                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                                                                        std::ofstream stream(fileName);
                                                                                                                                                                                                                                                                                                                                                                                        SuccessMontior m_(&stream, file_op_ok);
                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                        stream << "Hello world" << std::endl;
                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                        EmulateException(stream);
                                                                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                                                                    catch (std::exception& ex)
                                                                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                                                                        if (file_op_ok)
                                                                                                                                                                                                                                                                                                                                                                                            std::cout << "File operation succeeded" << std::endl;
                                                                                                                                                                                                                                                                                                                                                                                        else
                                                                                                                                                                                                                                                                                                                                                                                            std::cout << "File operation failed" << std::endl;
                                                                                                                                                                                                                                                                                                                                                                                        std::cout << "Exception occured: " << ex.what() << std::endl;
                                                                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                                                                }

                                                                                                                                                                                                                                                                                                                                                                              По-моему, это даже твоим требованим отвечает. :) SuccessMonitor - объект, закрывающий файл и проверяющий успешность факта закрытия. Как мы тут и обсуждали, его задача - среагировать на факт наличия ошибки и отрапортовать об этом вызывающему коду, который сам примет решение - а что же ему делать... И никаких двойных исключений и лишних наворотов.

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

                                                                                                                                                                                                                                                                                                                                                                              Добавлено
                                                                                                                                                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                              А ещё может содержать метод для отображения этого сообщения. И еще много чего может содержать и уметь.

                                                                                                                                                                                                                                                                                                                                                                              Ну да. Ты пишешь библиотеку классов. У тебя есть библиотечный объект-исключение. И откуда он знает - сообщать об ошибке на консоль или выкидывать мессаджбокс? Ась?
                                                                                                                                                                                                                                                                                                                                                                                Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                                Ну да. Ты пишешь библиотеку классов. У тебя есть библиотечный объект-исключение. И откуда он знает - сообщать об ошибке на консоль или выкидывать мессаджбокс? Ась?

                                                                                                                                                                                                                                                                                                                                                                                Элементарно. Во-первых, любое исключение собержит сообщение об ошибке, которое я могу вывести. Во-вторых:

                                                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                  public interface MessageDisplayer {
                                                                                                                                                                                                                                                                                                                                                                                      boolean displayMessage(String message);
                                                                                                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                  public class MyException extends Exception {
                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                      public void display(MessageDisplayer displayer) {
                                                                                                                                                                                                                                                                                                                                                                                          displayer.displayMessage(message);
                                                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                  ...
                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                  catch (MyException thrown) {
                                                                                                                                                                                                                                                                                                                                                                                      thrown.display(
                                                                                                                                                                                                                                                                                                                                                                                          new MessageDisplayer() {
                                                                                                                                                                                                                                                                                                                                                                                              public boolean displayMessage(String message) {
                                                                                                                                                                                                                                                                                                                                                                                                  MySecretDialogBuilder.showMessageBox(message);
                                                                                                                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                                                                                                                          });
                                                                                                                                                                                                                                                                                                                                                                                  }


                                                                                                                                                                                                                                                                                                                                                                                MessageDisplayer для конкретного приложения, разумеется, может быть написан один раз.

                                                                                                                                                                                                                                                                                                                                                                                Теперь относительно примера:

                                                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                  public class FileCreateException extends Exception {
                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                      public boolean isFileClosedSuccessfully() {
                                                                                                                                                                                                                                                                                                                                                                                          return ...
                                                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                  ...
                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                  catch (FileCreateException thrown) {
                                                                                                                                                                                                                                                                                                                                                                                      System.out.println(thrown.getMessage());
                                                                                                                                                                                                                                                                                                                                                                                      if (!thrown.isFileClosedSuccesfully()) {
                                                                                                                                                                                                                                                                                                                                                                                          System.out.println("Упс. Еще и файл не закрылся");
                                                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                                                  }

                                                                                                                                                                                                                                                                                                                                                                                По-моему, мой вариант проще и понятнее.
                                                                                                                                                                                                                                                                                                                                                                                  Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                  По-моему, мой вариант проще и понятнее.

                                                                                                                                                                                                                                                                                                                                                                                  Ты весь код покажи, а не выдержки. :) Я привел тебе весь необходимый код.

                                                                                                                                                                                                                                                                                                                                                                                  Добавлено
                                                                                                                                                                                                                                                                                                                                                                                  Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                  MessageDisplayer для конкретного приложения, разумеется, может быть написан один раз.

                                                                                                                                                                                                                                                                                                                                                                                  Вопрос только - как библиотека сможет создать нужный?
                                                                                                                                                                                                                                                                                                                                                                                    Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                                    Ты весь код покажи, а не выдержки.

                                                                                                                                                                                                                                                                                                                                                                                    Зная, к чему вы клоните, не буду :)

                                                                                                                                                                                                                                                                                                                                                                                    Хотя на самом деле я вряд ли буду отлавливать все возможные исключения в подобных случаях, меня будет интересовать только факт возникновения ошибки. Поэтому метод записи будет выглядеть примерно так:

                                                                                                                                                                                                                                                                                                                                                                                    ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                      public void writeFile(String fileName, byte[] buffer) throws IOException {
                                                                                                                                                                                                                                                                                                                                                                                          OutputStream ostream = new FileOutputStream(fileName);
                                                                                                                                                                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                                                                                                          try {
                                                                                                                                                                                                                                                                                                                                                                                              ostream.write(buffer);
                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                          finally {
                                                                                                                                                                                                                                                                                                                                                                                              ostream.close();
                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                      }


                                                                                                                                                                                                                                                                                                                                                                                    Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                                    Вопрос только - как библиотека сможет создать нужный?

                                                                                                                                                                                                                                                                                                                                                                                    Библиотека не будет ничего создавать, вы не так поняли. Метод display() исключения принимает параметром интерфейс, который реализует пользователь библиотеки.
                                                                                                                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                      параметром интерфейс, который реализует пользователь библиотеки.

                                                                                                                                                                                                                                                                                                                                                                                      Не понял. Вот библиотечный метод поймал исключение, выброшенное методом close. Его дальнейшие действия?

                                                                                                                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                      Поэтому метод записи будет выглядеть примерно так:

                                                                                                                                                                                                                                                                                                                                                                                      И где тут обработка ошибки в методе close?
                                                                                                                                                                                                                                                                                                                                                                                        Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                                        Вот библиотечный метод поймал исключение, выброшенное методом close. Его дальнейшие действия?

                                                                                                                                                                                                                                                                                                                                                                                        Выбросил другое исключение, передав исходное параметром; в коде, использующем библиотеку, вызывается метод display() исключения, которому передаётся реализация интерфейса, способная отобразить сообщение об ошибке.

                                                                                                                                                                                                                                                                                                                                                                                        Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                                        И где тут обработка ошибки в методе close?

                                                                                                                                                                                                                                                                                                                                                                                        Если метод close() выбросит исключение, то именно оно будет передано в вызывающий код.
                                                                                                                                                                                                                                                                                                                                                                                        Сообщение отредактировано: wind -
                                                                                                                                                                                                                                                                                                                                                                                          Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                          Если метод close() выбросит исключение, то именно оно будет передано в вызывающий код.

                                                                                                                                                                                                                                                                                                                                                                                          А если finally вызывается из за того, что уже летит какое-то другое исключение? Как отреагирует рантайм на возникновение второго исключения?


                                                                                                                                                                                                                                                                                                                                                                                          Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                          Выбросил другое исключение, передав исходное параметром; в коде, использующем библиотеку, вызывается метод display() исключения, которому передаётся реализация интерфейса, способная отобразить сообщение об ошибке.

                                                                                                                                                                                                                                                                                                                                                                                          Брррр. То есть опять агрегированные исключения? А как же на них адекватным образом реагировать? Мнда... Это что же я должен - поймать абстрактное библиотечное исключение, выдрать из него исходное исключение, проверить - мое/не мое, и если мое, то произвести необходимую обработку? Так что ли?

                                                                                                                                                                                                                                                                                                                                                                                          Добавлено
                                                                                                                                                                                                                                                                                                                                                                                          Видимо, я чего-то не понимаю...
                                                                                                                                                                                                                                                                                                                                                                                            Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                                            А если finally вызывается из за того, что уже летит какое-то другое исключение? Как отреагирует рантайм на возникновение второго исключения?

                                                                                                                                                                                                                                                                                                                                                                                            Первое будет "замещено", выбросится второе.

                                                                                                                                                                                                                                                                                                                                                                                            Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                                            То есть опять агрегированные исключения? А как же на них адекватным образом реагировать?

                                                                                                                                                                                                                                                                                                                                                                                            Да нет же :) Точнее, это не важно.

                                                                                                                                                                                                                                                                                                                                                                                            У вас есть метод, создающий файл. В случае ошибки он выбрасывает исключение - "файл создать не удалось". Для вызывающего кода этого вполне достаточно, но пользователю хотелось бы узнать, почему. Мы же все приверженцы ООП, надеюсь :) Так почему бы не заставить исключение самостоятельно оповестить пользователя о причинах? В принципе, для этого там и так есть поле message, но мы пойдём дальше: в классе исключения добавляем метод display(). Естественно, реализуя библиотечный метод, мы не знаем, как именно следует отображать информацию об ошибке. Для этого определяем в библиотеке интерфейс, реализация которого это уже знает (потому как живёт уже в приложении, а не в библиотеке); метод display() принимает эту реализацию в качестве параметра.
                                                                                                                                                                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                              Первое будет "замещено", выбросится второе.

                                                                                                                                                                                                                                                                                                                                                                                              Зашибись... А если первое было важнее, чем второе? Если вызывающему коду совершенно по барабану - почему не смог закрыться файл, но очень важно - что же произошло до этого? Как быть в этом случае?

                                                                                                                                                                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                              У вас есть метод, создающий файл. В случае ошибки он выбрасывает исключение - "файл создать не удалось". Для вызывающего кода этого вполне достаточно, но пользователю хотелось бы узнать, почему. Мы же все приверженцы ООП, надеюсь :) Так почему бы не заставить исключение самостоятельно оповестить пользователя о причинах?

                                                                                                                                                                                                                                                                                                                                                                                              Да дело то уже не в пользователе. Согласись, для кода может быть существенен факт того, что файл не мог создаться по причине отсутствия доступа к директории, или по причине существования аналогичного файла. В одном случае, положим, нужно ругаться. В другом - любым способом удалить существующий файл. И как это грамотно разрулить в случае агрегированных исключений? Динамически проверять тип того, что лежит в агрегате... Гм...
                                                                                                                                                                                                                                                                                                                                                                                                Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                                                А если первое было важнее, чем второе? Если вызывающему коду совершенно по барабану - почему не смог закрыться файл, но очень важно - что же произошло до этого? Как быть в этом случае?

                                                                                                                                                                                                                                                                                                                                                                                                Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                                                Согласись, для кода может быть существенен факт того, что файл не мог создаться по причине отсутствия доступа к директории, или по причине существования аналогичного файла.

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

                                                                                                                                                                                                                                                                                                                                                                                                Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                                                И как это грамотно разрулить в случае агрегированных исключений? Динамически проверять тип того, что лежит в агрегате...

                                                                                                                                                                                                                                                                                                                                                                                                Как правило, сохранённая цепочка исключений используется именно для отображения информации об ошибке. Если же мой код будет зависеть от источника ошибки, я создам типизированные исключения либо буду передавать дополнительную информацию в исключении. Ведь любом случае, количество возможных ошибок конечно.
                                                                                                                                                                                                                                                                                                                                                                                                  вот нашел в книге про яву такой тестик, автор уверяет что на нем ява выигрывает у с++
                                                                                                                                                                                                                                                                                                                                                                                                  вот сырцы (единственное изменение, я цикл for самый верхний добавил)
                                                                                                                                                                                                                                                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                    #include <bitset>
                                                                                                                                                                                                                                                                                                                                                                                                    #include <iostream>
                                                                                                                                                                                                                                                                                                                                                                                                    #include <ctime>
                                                                                                                                                                                                                                                                                                                                                                                                    #include <conio.h>
                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                    using namespace std;
                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                    int _main(int argc, char* argv[])
                                                                                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                                                                                        const int N = 2000000;
                                                                                                                                                                                                                                                                                                                                                                                                        clock_t cstart = clock();
                                                                                                                                                                                                                                                                                                                                                                                                        int count;
                                                                                                                                                                                                                                                                                                                                                                                                        for(int xxx = 0;xxx<=100;xxx++)
                                                                                                                                                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                                                                                                                                                            bitset<N + 1> b;
                                                                                                                                                                                                                                                                                                                                                                                                            count = 0;
                                                                                                                                                                                                                                                                                                                                                                                                            int i;
                                                                                                                                                                                                                                                                                                                                                                                                            for(i=2;i<=N;i++)
                                                                                                                                                                                                                                                                                                                                                                                                                b.set(i);
                                                                                                                                                                                                                                                                                                                                                                                                            i=2;
                                                                                                                                                                                                                                                                                                                                                                                                            while(i*i<=N)
                                                                                                                                                                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                                                                                                                                                                if(b.test(i))
                                                                                                                                                                                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                                                                                                                                                                                    count++;
                                                                                                                                                                                                                                                                                                                                                                                                                    int k = 2*i;
                                                                                                                                                                                                                                                                                                                                                                                                                    while(k <= N)
                                                                                                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                                                                                                        b.reset(k);
                                                                                                                                                                                                                                                                                                                                                                                                                        k += i;
                                                                                                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                                                                                                i++;
                                                                                                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                            while(i<=N)
                                                                                                                                                                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                                                                                                                                                                if(b.test(i))
                                                                                                                                                                                                                                                                                                                                                                                                                    count++;
                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                i++;
                                                                                                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                                                                                                        clock_t cend = clock();
                                                                                                                                                                                                                                                                                                                                                                                                        double millis = 1000.0*(cend-cstart)/CLOCKS_PER_SEC;
                                                                                                                                                                                                                                                                                                                                                                                                        cout << count << " primes\n" << millis << " millisecond\n";
                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                        getch();
                                                                                                                                                                                                                                                                                                                                                                                                        return 0;
                                                                                                                                                                                                                                                                                                                                                                                                    }


                                                                                                                                                                                                                                                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                    package test;
                                                                                                                                                                                                                                                                                                                                                                                                    import java.util.*;
                                                                                                                                                                                                                                                                                                                                                                                                    /**
                                                                                                                                                                                                                                                                                                                                                                                                     *
                                                                                                                                                                                                                                                                                                                                                                                                     * @author impik777
                                                                                                                                                                                                                                                                                                                                                                                                     */
                                                                                                                                                                                                                                                                                                                                                                                                    public class Main {
                                                                                                                                                                                                                                                                                                                                                                                                        public static void main(String[] args) {
                                                                                                                                                                                                                                                                                                                                                                                                            int n = 2000000;
                                                                                                                                                                                                                                                                                                                                                                                                            long start = System.currentTimeMillis();
                                                                                                                                                                                                                                                                                                                                                                                                           int count = 0;
                                                                                                                                                                                                                                                                                                                                                                                                            for(int xxx = 0;xxx<=100;xxx++)
                                                                                                                                                                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                                                                                                                                                                BitSet b = new BitSet(n+1);
                                                                                                                                                                                                                                                                                                                                                                                                                count = 0;
                                                                                                                                                                                                                                                                                                                                                                                                                int i;
                                                                                                                                                                                                                                                                                                                                                                                                                for(i=2;i<=n;i++)
                                                                                                                                                                                                                                                                                                                                                                                                                    b.set(i);
                                                                                                                                                                                                                                                                                                                                                                                                                i=2;
                                                                                                                                                                                                                                                                                                                                                                                                                while(i*i<=n)
                                                                                                                                                                                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                                                                                                                                                                                    if(b.get(i))
                                                                                                                                                                                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                                                                                                                                                                                        count++;
                                                                                                                                                                                                                                                                                                                                                                                                                        int k = 2*i;
                                                                                                                                                                                                                                                                                                                                                                                                                        while(k<=n)
                                                                                                                                                                                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                                                                                                                                                                                            b.clear(k);
                                                                                                                                                                                                                                                                                                                                                                                                                            k += i;
                                                                                                                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                                                                                                    i++;
                                                                                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                while (i <= n)
                                                                                                                                                                                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                                                                                                                                                                                    if(b.get(i))
                                                                                                                                                                                                                                                                                                                                                                                                                        count++;
                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                    i++;
                                                                                                                                                                                                                                                                                                                                                                                                                }
                                                                                                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                            long end = System.currentTimeMillis();
                                                                                                                                                                                                                                                                                                                                                                                                            System.out.println(count + " primes");
                                                                                                                                                                                                                                                                                                                                                                                                            System.out.println((end - start) + " milliseconds");  
                                                                                                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                                                                                                    }


                                                                                                                                                                                                                                                                                                                                                                                                  запускал я напрямую в ИДЕ, результаты
                                                                                                                                                                                                                                                                                                                                                                                                  Java 1.6 - 15 сек
                                                                                                                                                                                                                                                                                                                                                                                                  VC++ 2005 (Release) - 3 сек
                                                                                                                                                                                                                                                                                                                                                                                                  у кого какие коментарии?
                                                                                                                                                                                                                                                                                                                                                                                                  категорически прошу без холиваров :rolleyes:

                                                                                                                                                                                                                                                                                                                                                                                                  Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                  gcc отработал 5 сек
                                                                                                                                                                                                                                                                                                                                                                                                    А чем компилировать сёвый код любопытным?
                                                                                                                                                                                                                                                                                                                                                                                                      Выкинь #include "stdafx.h" и замени _tmain на main. Это уродливые проявления MFC.
                                                                                                                                                                                                                                                                                                                                                                                                      Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                      у кого какие коментарии?
                                                                                                                                                                                                                                                                                                                                                                                                      А какие тут могут быть комментарии? Эффективность варианта C++ ограничена только эффективностью релизации класса bitset.
                                                                                                                                                                                                                                                                                                                                                                                                        Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                        А чем компилировать сёвый код любопытным?

                                                                                                                                                                                                                                                                                                                                                                                                        сорри, см аттач

                                                                                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                        Цитата trainer @
                                                                                                                                                                                                                                                                                                                                                                                                        Выкинь #include "stdafx.h" и замени _tmain на main. Это уродливые проявления MFC.

                                                                                                                                                                                                                                                                                                                                                                                                        это студия автоматом создавала. исправил.

                                                                                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                        Цитата trainer @
                                                                                                                                                                                                                                                                                                                                                                                                        А какие тут могут быть комментарии?

                                                                                                                                                                                                                                                                                                                                                                                                        в тестах выше производительность ява кода во столько раз не отставала +
                                                                                                                                                                                                                                                                                                                                                                                                        Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                        вот нашел в книге про яву такой тестик, автор уверяет что на нем ява выигрывает у с++

                                                                                                                                                                                                                                                                                                                                                                                                        причем выйгрыш был 330 миллисек у С++(gcc) против 105 у Java(1.5 SE) (на компе автора ессно)
                                                                                                                                                                                                                                                                                                                                                                                                        ВОт мне интересно - это автор наврал - или я что-то не так сделал.

                                                                                                                                                                                                                                                                                                                                                                                                        Цитата trainer @
                                                                                                                                                                                                                                                                                                                                                                                                        Эффективность варианта C++ ограничена только эффективностью релизации класса bitset.

                                                                                                                                                                                                                                                                                                                                                                                                        :no: не совсем, большая часть кода - это обычные математические вычисления. ОТ битсета там только обращение по индексу, тут особо не с оптимизируешь.
                                                                                                                                                                                                                                                                                                                                                                                                        Прикреплённый файлПрикреплённый файлbin.rar (75.97 Кбайт, скачиваний: 93)
                                                                                                                                                                                                                                                                                                                                                                                                          Цитата impik777 @

                                                                                                                                                                                                                                                                                                                                                                                                          причем выйгрыш был 330 миллисек у С++(gcc) против 105 у Java(1.5 SE) (на компе автора ессно)
                                                                                                                                                                                                                                                                                                                                                                                                          ВОт мне интересно - это автор наврал - или я что-то не так сделал.

                                                                                                                                                                                                                                                                                                                                                                                                          Ну, если компилировать C++-ый код (с помощью gcc) без опции -O2, то примерно такие показатели и будут. Но кто при подготовке релизных компонент не включает оптимизацию? :)
                                                                                                                                                                                                                                                                                                                                                                                                            gcc:
                                                                                                                                                                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                              4421 millisecond

                                                                                                                                                                                                                                                                                                                                                                                                            vs 2005:
                                                                                                                                                                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                              3346 millisecond

                                                                                                                                                                                                                                                                                                                                                                                                            sun jre 1.6.0:
                                                                                                                                                                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                              22547 milliseconds
                                                                                                                                                                                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                              sun jre 1.6.0:

                                                                                                                                                                                                                                                                                                                                                                                                              22547 milliseconds

                                                                                                                                                                                                                                                                                                                                                                                                              а если в режиме сервака?

                                                                                                                                                                                                                                                                                                                                                                                                              получается в Java как можно больше перебрасывать на библиотеки?
                                                                                                                                                                                                                                                                                                                                                                                                              у wind'а же код не такой тормознутый получался
                                                                                                                                                                                                                                                                                                                                                                                                                Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                                а если в режиме сервака?
                                                                                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                                  11953 milliseconds


                                                                                                                                                                                                                                                                                                                                                                                                                Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                                получается в Java как можно больше перебрасывать на библиотеки?

                                                                                                                                                                                                                                                                                                                                                                                                                Не понял мысли.
                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                                  Не понял мысли.

                                                                                                                                                                                                                                                                                                                                                                                                                  есть мнение что на предыдущих тестах у явы был лучший результат засчет
                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                  Логично предполагать, что если ты часто вызываешь функцию сортировки, или поиску по стандартному массиву/словарю и т. п., то код будет работать достаточно быстро, т. к. есть возможность максимально оптимизировать такого рода операции - на то они и библиотечные. Особенно для стандартных типов. А вот в решете Эрастофена в основном работает пользовательский код, т. к. операция доступа к биту - достаточно примитивна, сколько ты ее не оптимизируй, очень быстро упрешься в потолок.
                                                                                                                                                                                                                                                                                                                                                                                                                    Нет, не думаю. Нет и пока не было ни одного прецедента заподозрить исполняющую среду в особенном отношении к библиотечным классам. В данном java коде я вижу другую дыру, куда утекает время - это new BitSet(). В c++-примере, очевидно, объект будет размещён в стеке, тогда как в java - всегда в куче. Это, как говорят в Одессе, две большие разницы. Или четыре маленьких :) Ну и в реализацию java.util.BitSet я не заглядывал.
                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                                      В данном java коде я вижу другую дыру, куда утекает время - это new BitSet().

                                                                                                                                                                                                                                                                                                                                                                                                                      :no:
                                                                                                                                                                                                                                                                                                                                                                                                                      вынес new за цикл
                                                                                                                                                                                                                                                                                                                                                                                                                      стало 14,5 против 14,7
                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                                      Ну и в реализацию java.util.BitSet я не заглядывал.

                                                                                                                                                                                                                                                                                                                                                                                                                      :no: найти бит по индексу - не такая крутая операция
                                                                                                                                                                                                                                                                                                                                                                                                                        Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                                        стало 14,5 против 14,7

                                                                                                                                                                                                                                                                                                                                                                                                                        Слишком мало. В java операция new кушает весьма и весьма много времени. Если повезёт, вечером доберусь до c++ компилятора, посмотрю.
                                                                                                                                                                                                                                                                                                                                                                                                                          Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                                          В java операция new кушает весьма и весьма много времени.

                                                                                                                                                                                                                                                                                                                                                                                                                          :no:
                                                                                                                                                                                                                                                                                                                                                                                                                          в статьях дяди убеждали, что выделение памяти на яве как на стеке, смещение указателя в массиве молодого поколения

                                                                                                                                                                                                                                                                                                                                                                                                                          http://www.ibm.com/developerworks/ru/library/j-jtp09275/index.html

                                                                                                                                                                                                                                                                                                                                                                                                                          вот здесь кажется
                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                                            в статьях дяди убеждали, что выделение памяти на яве как на стеке, смещение указателя в массиве молодого поколения

                                                                                                                                                                                                                                                                                                                                                                                                                            Я уже хотел, как обычно, обругать за глупость дядек из ibm (это уже стало традицией в последнее время, хе-хе), но в этой статье ни о чём подобном не пишут. Если вы немного задумаетесь, то поймёте, что стековая аллокация в java невозможна.

                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                                            Слишком мало. В java операция new кушает весьма и весьма много времени. Если повезёт, вечером доберусь до c++ компилятора, посмотрю.

                                                                                                                                                                                                                                                                                                                                                                                                                            А, точно. Меня загипнотизировала цифра 2000000, а там только сто итераций :)
                                                                                                                                                                                                                                                                                                                                                                                                                            Сообщение отредактировано: wind -
                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                                              но в этой статье ни о чём подобном не пишут.

                                                                                                                                                                                                                                                                                                                                                                                                                              Ээээээээээээ.... Мои глаза меня обманывают?
                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                              Язык Java не предлагает никакого способа точно расположить объект в стеке, но этот факт не мешает JVM использовать стековую аллокацию, где это уместно. JVM может использовать технологию, именуемую escape-анализ, с помощью которой можно сказать, что определенные объекты удерживаются в одном потоке в течение всего жизненного цикла, а он связан со временем существования данного стекового фрейма. Такие объекты можно безопасно располагать в стеке вместо массива. Что даже лучше для маленьких объектов, JVM может полностью оптимизировать аллокацию и просто поднять поля объекта в списки.


                                                                                                                                                                                                                                                                                                                                                                                                                              Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                              И здесь, видимо, не про Java:
                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                              Escape-анализ является оптимизацией, о которой уже давно говорилось, и наконец-то вот она - текущие сборки Mustang (Java SE 6) могут осуществлять escape-анализ и конвертировать аллокацию массива в стековую аллокацию (или без аллокации) там, где это уместно. Использование escape-анализа для устранения некоторых результатов аллокаций с более быстрым средним временем аллокации, уменьшенным потреблением ОЗУ и меньшим количеством кэш-промахов. Кроме этого, оптимизирование некоторых аллокаций уменьшает давление на сборщик мусора и позволяет реже запускать сборку.

                                                                                                                                                                                                                                                                                                                                                                                                                              :whistle:
                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата Flex Ferrum @
                                                                                                                                                                                                                                                                                                                                                                                                                                Ээээээээээээ.... Мои глаза меня обманывают?

                                                                                                                                                                                                                                                                                                                                                                                                                                Можно сказать и так. Там ведь не написано о том, что можно ожидать размещения объекта в стеке при некоторых условиях, там лишь описан некоторый механизм, который "может" это делать. "Может" ни разу не означает "делает".
                                                                                                                                                                                                                                                                                                                                                                                                                                  Чуть-чуть аргументов, чтобы не повторяться :)

                                                                                                                                                                                                                                                                                                                                                                                                                                  Если проанализировать возможности гипотетического escape-анализатора, то он оказывается зажат массой условий, крайне редко встречающихся. А самое главное - он должен работать в runtime (рефлексии никто не отменял).

                                                                                                                                                                                                                                                                                                                                                                                                                                  А теперь проиллюстрирую возможности Мустанга, который якобы "умеет размещать в стеке массивы":
                                                                                                                                                                                                                                                                                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                                                    public class Test {
                                                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                                        public static void allocate() {
                                                                                                                                                                                                                                                                                                                                                                                                                                            long[] longs = new long[100];
                                                                                                                                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        public static void main(String[] args) throws IOException {
                                                                                                                                                                                                                                                                                                                                                                                                                                            allocate();
                                                                                                                                                                                                                                                                                                                                                                                                                                            System.in.read();
                                                                                                                                                                                                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                    }

                                                                                                                                                                                                                                                                                                                                                                                                                                  При запуске этого примера на sun jre 1.6.0 (Мустанг) массив не только будет создан, но создан именно в куче.
                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                                                    Я уже хотел, как обычно, обругать за глупость дядек из ibm (это уже стало традицией в последнее время, хе-хе), но в этой статье ни о чём подобном не пишут.


                                                                                                                                                                                                                                                                                                                                                                                                                                    короче, дядьки наговорили много умных и красивых слов за которыми в реальности ничего не стоит?
                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                                                      короче, дядьки наговорили много умных и красивых слов за которыми в реальности ничего не стоит?

                                                                                                                                                                                                                                                                                                                                                                                                                                      В части стековой аллокации - именно так.
                                                                                                                                                                                                                                                                                                                                                                                                                                        impik777, в ваших компиляторах размерность unsigned long какая?
                                                                                                                                                                                                                                                                                                                                                                                                                                          4 байта
                                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                                                            4 байта

                                                                                                                                                                                                                                                                                                                                                                                                                                            А в java - 8. Сделайте пример на c++ эквивалентным этому (свой bitset, его размещение в куче):

                                                                                                                                                                                                                                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                                                              package test;
                                                                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                              public class Main {
                                                                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                                  static class BitSet {
                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                      private final int[] ints;
                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                      public BitSet(int count) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                          ints = new int[(count >> 5) + ((count & 0x1f) != 0 ? 1 : 0)];
                                                                                                                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                      public boolean get(int number) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                          return (ints[(number >> 5)] & (1 << (number & 0x1f))) != 0;
                                                                                                                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                      public void set(int number) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                          ints[(number >> 5)] |= (1 << (number & 0x1f));
                                                                                                                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                                      public void clear(int number) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                          ints[(number >> 5)] &= ~(1 << (number & 0x1f));
                                                                                                                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                                  public static void main(String... args) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                      int n = 2000000;
                                                                                                                                                                                                                                                                                                                                                                                                                                                      long start = System.currentTimeMillis();
                                                                                                                                                                                                                                                                                                                                                                                                                                                      int count = 0;
                                                                                                                                                                                                                                                                                                                                                                                                                                                      for (int xxx = 0; xxx <= 100; xxx++) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                          BitSet b = new BitSet(n + 1);
                                                                                                                                                                                                                                                                                                                                                                                                                                                          count = 0;
                                                                                                                                                                                                                                                                                                                                                                                                                                                          int i;
                                                                                                                                                                                                                                                                                                                                                                                                                                                          for (i = 2; i <= n; i++)
                                                                                                                                                                                                                                                                                                                                                                                                                                                              b.set(i);
                                                                                                                                                                                                                                                                                                                                                                                                                                                          i = 2;
                                                                                                                                                                                                                                                                                                                                                                                                                                                          while (i * i <= n) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                              if (b.get(i)) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  count++;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  int k = 2 * i;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  while (k <= n) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      b.clear(k);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      k += i;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                                                                                                                                                                                              i++;
                                                                                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                                          while (i <= n) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                              if (b.get(i))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  count++;
                                                                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                                              i++;
                                                                                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                                                                                                                                                      long end = System.currentTimeMillis();
                                                                                                                                                                                                                                                                                                                                                                                                                                                      System.out.println(count + " primes");
                                                                                                                                                                                                                                                                                                                                                                                                                                                      System.out.println((end - start) + " milliseconds");
                                                                                                                                                                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                              }

                                                                                                                                                                                                                                                                                                                                                                                                                                            Что получится?
                                                                                                                                                                                                                                                                                                                                                                                                                                              готово

                                                                                                                                                                                                                                                                                                                                                                                                                                              Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                                                              А в java - 8.

                                                                                                                                                                                                                                                                                                                                                                                                                                              а причем тут лонг, он же в коде не используется (кроме времени)?

                                                                                                                                                                                                                                                                                                                                                                                                                                              Добавлено
                                                                                                                                                                                                                                                                                                                                                                                                                                              мои результаты
                                                                                                                                                                                                                                                                                                                                                                                                                                              C++ - 2.5 сек
                                                                                                                                                                                                                                                                                                                                                                                                                                              Java - 4.1 сек
                                                                                                                                                                                                                                                                                                                                                                                                                                              уже терпимо :)
                                                                                                                                                                                                                                                                                                                                                                                                                                              Прикреплённый файлПрикреплённый файлtest2.rar (4.52 Кбайт, скачиваний: 110)
                                                                                                                                                                                                                                                                                                                                                                                                                                                Может кому интересно.

                                                                                                                                                                                                                                                                                                                                                                                                                                                Протестил код impik777 на своей машине

                                                                                                                                                                                                                                                                                                                                                                                                                                                С++ 2.387
                                                                                                                                                                                                                                                                                                                                                                                                                                                C# (release NET 3.5) 2.541

                                                                                                                                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                                                                     public class BitSet
                                                                                                                                                                                                                                                                                                                                                                                                                                                     {    
                                                                                                                                                                                                                                                                                                                                                                                                                                                          private readonly int[] ints;
                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                          public BitSet(int count) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                              ints = new int[(count >> 5) + ((count & 0x1f) != 0 ? 1 : 0)];
                                                                                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                          public bool get(int number) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                              return (ints[(number >> 5)] & (1 << (number & 0x1f))) != 0;
                                                                                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                          public void set(int number) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                              ints[(number >> 5)] |= (1 << (number & 0x1f));
                                                                                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                                                                                          public void clear(int number) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                              ints[(number >> 5)] &= ~(1 << (number & 0x1f));
                                                                                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                                                                                      class Program
                                                                                                                                                                                                                                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                                                                                                                                                                                                                                          static void Main(string[] args)
                                                                                                                                                                                                                                                                                                                                                                                                                                                          {
                                                                                                                                                                                                                                                                                                                                                                                                                                                              int n = 2000000;
                                                                                                                                                                                                                                                                                                                                                                                                                                                              Stopwatch watch = new Stopwatch();
                                                                                                                                                                                                                                                                                                                                                                                                                                                              watch.Start();
                                                                                                                                                                                                                                                                                                                                                                                                                                                              int count = 0;
                                                                                                                                                                                                                                                                                                                                                                                                                                                              for (int xxx = 0; xxx <= 100; xxx++)
                                                                                                                                                                                                                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  BitSet b = new BitSet(n + 1);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  count = 0;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  int i;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  for (i = 2; i <= n; i++)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      b.set(i);
                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  i = 2;
                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  while (i * i <= n)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      if (b.get(i))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          count++;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          int k = 2 * i;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          while (k <= n)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              b.clear(k);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              k += i;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      i++;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  while (i <= n)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      if (b.get(i))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          count++;
                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      i++;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  }
                                                                                                                                                                                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                                                                                                                                                              watch.Stop();
                                                                                                                                                                                                                                                                                                                                                                                                                                                              Console.WriteLine(count + " primes");
                                                                                                                                                                                                                                                                                                                                                                                                                                                              Console.WriteLine(watch.ElapsedMilliseconds + " milliseconds");
                                                                                                                                                                                                                                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                                                                                                                                                                                                                                      }
                                                                                                                                                                                                                                                                                                                                                                                                                                                  juice, я Java вариант можешь протестить?

                                                                                                                                                                                                                                                                                                                                                                                                                                                  juice, а какой будет результат, если на шарпе использовать библиотечный битсет?
                                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                                                                    juice, я Java вариант можешь протестить?

                                                                                                                                                                                                                                                                                                                                                                                                                                                    Выложи, откомпиленую Java версию, Runtime у меня вроде стоит.
                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата juice @
                                                                                                                                                                                                                                                                                                                                                                                                                                                      Выложи, откомпиленую Java версию

                                                                                                                                                                                                                                                                                                                                                                                                                                                      Прикреплённый файлПрикреплённый файлJavaTest.rar (1.38 Кбайт, скачиваний: 118)
                                                                                                                                                                                                                                                                                                                                                                                                                                                        Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                                                                        juice, я Java вариант можешь протестить?

                                                                                                                                                                                                                                                                                                                                                                                                                                                        Java (SE 1.6) 3.361
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                                                                          а причем тут лонг, он же в коде не используется (кроме времени)?

                                                                                                                                                                                                                                                                                                                                                                                                                                                          java.util.BitSet, хранение бит.
                                                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата impik777 @
                                                                                                                                                                                                                                                                                                                                                                                                                                                            juice, а какой будет результат, если на шарпе использовать библиотечный битсет?

                                                                                                                                                                                                                                                                                                                                                                                                                                                            Сложно сказать в .NET нет стандартного битсета есть BitArray, его можно использовать как Bitset за некоторыми оговорками.
                                                                                                                                                                                                                                                                                                                                                                                                                                                            Если использовать BitArray, то результат 6.961, но повторюсь BitArray не есть BitSet в чистом виде.
                                                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                                                                              Чуть-чуть аргументов, чтобы не повторяться :)

                                                                                                                                                                                                                                                                                                                                                                                                                                                              Если проанализировать возможности гипотетического escape-анализатора, то он оказывается зажат массой условий, крайне редко встречающихся. А самое главное - он должен работать в runtime (рефлексии никто не отменял).

                                                                                                                                                                                                                                                                                                                                                                                                                                                              Не так уж редко они встречаются, и всё работает.

                                                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата

                                                                                                                                                                                                                                                                                                                                                                                                                                                              А теперь проиллюстрирую возможности Мустанга, который якобы "умеет размещать в стеке массивы":

                                                                                                                                                                                                                                                                                                                                                                                                                                                              При запуске этого примера на sun jre 1.6.0 (Мустанг) массив не только будет создан, но создан именно в куче.

                                                                                                                                                                                                                                                                                                                                                                                                                                                              Ну естественно, Вы же ему ни одного шанса не дали для оптимизаций - код просто проинтерпретировался. Да и массив стоило бы сделать поменьше (800 байт - жирновато для стекового размещения)

                                                                                                                                                                                                                                                                                                                                                                                                                                                              Сделайте там выделение небольшого массива или объекта, вызов allocate() поместите в цикл и запустите на HotSpot Server.

                                                                                                                                                                                                                                                                                                                                                                                                                                                              На Excelsior JET можно и без цикла, только inline-подстановку пришлось выключить:

                                                                                                                                                                                                                                                                                                                                                                                                                                                              ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                                                                                import java.io.*;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                public class Test {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    public static void print0(long a[]) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        System.out.println(a[0]);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    public static void main(String[] args) throws IOException {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        long[] longs = new long[10];
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        longs[0] = args.length;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        print0(longs);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        System.in.read();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                }


                                                                                                                                                                                                                                                                                                                                                                                                                                                              longs успешно разместился на стеке и передался в print0.

                                                                                                                                                                                                                                                                                                                                                                                                                                                              Единственное замечание: HotSpot 6 не умеет размещать на стеке массивы переменной длины, в отличие от Excelsior JET.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                Ну естественно, Вы же ему ни одного шанса не дали для оптимизаций - код просто проинтерпретировался. Да и массив стоило бы сделать поменьше (800 байт - жирновато для стекового размещения)

                                                                                                                                                                                                                                                                                                                                                                                                                                                                Во-первых, не интерпретировался - это легко можно проверить, запустив jvm в режиме интерпретации. Во-вторых, одно другому не мешает. В-третьих, размер стека - 1 мегабайт; для данного размера 800 байт - пшик. Ну и последнее - если в таких идеальных условиях, которые были предоставлены, массив не попадает в стек, то это уже клиника.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                Не так уж редко они встречаются, и всё работает.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                На Excelsior JET можно и без цикла, только inline-подстановку пришлось выключить:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                Здесь мы говорим не о JET и ему подобных. Компиляция java-кода в бинарный - истинное извращение; для создания нативного кода есть инструменты получше.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                Добавлено

                                                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                Сделайте там выделение небольшого массива или объекта, вызов allocate() поместите в цикл и запустите на HotSpot Server.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                Как определить происходящее в таком сценарии, не подскажете?
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Ну естественно, Вы же ему ни одного шанса не дали для оптимизаций - код просто проинтерпретировался. Да и массив стоило бы сделать поменьше (800 байт - жирновато для стекового размещения)

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Во-первых, не интерпретировался - это легко можно проверить, запустив jvm в режиме интерпретации.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Интерпертировался - HotSpot компилирует только горячие методы, а тут их нет.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Во-вторых, одно другому не мешает.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Теоретически да, а практически - зачем размещать объект холодного метода на стеке?
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  В-третьих, размер стека - 1 мегабайт; для данного размера 800 байт - пшик. Ну и последнее - если в таких идеальных условиях, которые были предоставлены, массив не попадает в стек, то это уже клиника.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  А Вы знаете способ определить глубину стека, требуемую Java-программе? Там же следом вызов - может, он рекурсивный и именно этих 800 байт ему и не хватит?
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Не так уж редко они встречаются, и всё работает.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  На Excelsior JET можно и без цикла, только inline-подстановку пришлось выключить:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Здесь мы говорим не о JET и ему подобных. Компиляция java-кода в бинарный - истинное извращение; для создания нативного кода есть инструменты получше.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Тема, если я не ошибаюсь "Сравнение производительности Java и Delphi/C++", где в ней говорится, что рассматриваются только реализации Java с динамической компиляцией? С GCJ не вполне корректно сравнивать, так как он не прошёл тесты совместимости, но Excelsior JET-то полностью проходит Java SE 6 TCK, чем он хуже HotSpot?

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Сделайте там выделение небольшого массива или объекта, вызов allocate() поместите в цикл и запустите на HotSpot Server.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Как определить происходящее в таком сценарии, не подскажете?


                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Если Вы не умеете подглядывать в код сгенерированный HotSpotом, можно замерить потребление памяти в куче и на стеке в случае когда предположительно размещение объектов на стеке имеет место и когда нет.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Интерпертировался - HotSpot компилирует только горячие методы, а тут их нет.

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Теоретически да, а практически - зачем размещать объект холодного метода на стеке?

                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Странный вопрос. Затем, чтобы не тратить времени на размещение его в куче. Даже если это интерпретируемый метод (что маловероятно - см. выше), это принесёт пользу.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    А Вы знаете способ определить глубину стека, требуемую Java-программе? Там же следом вызов - может, он рекурсивный и именно этих 800 байт ему и не хватит?

                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Безосновательный домысел. Даже если бы в виртуальную машину был встроен механизм предсказания требуемой глубины стека (что уже чистая фантастика), в данном примере он не был бы причиной запрета на размещение массива из 800 байт в стеке. Потому как больше там ничего не размещается.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Тема, если я не ошибаюсь "Сравнение производительности Java и Delphi/C++", где в ней говорится, что рассматриваются только реализации Java с динамической компиляцией?

                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Я (инициатор создания темы) сейчас это вам говорю.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Если Вы не умеете подглядывать в код сгенерированный HotSpotом, можно замерить потребление памяти в куче и на стеке в случае когда предположительно размещение объектов на стеке имеет место и когда нет.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                    При многократных вызовах в процесс вмешается сборщик мусора, поэтому зарегистрировать средствами java выделение/невыделение памяти не удастся ;) Кстати, а вы умеете подглядывать в код, сгенерированный JIT? Научили бы, что ли.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Тема, если я не ошибаюсь "Сравнение производительности Java и Delphi/C++", где в ней говорится, что рассматриваются только реализации Java с динамической компиляцией?

                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Я (инициатор создания темы) сейчас это вам говорю.

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ЗЫ. Кстати, первое сообщение в теме - не Ваше, если уж на то пошло. Ваше - второе.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Скажите, только без обид, здесь принята модерация темы создателем темы?

                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Нет, но желательно не оффтопить. Если хотите сравнить компиляторы delphi и c++ с компиляторами же java, создайте отдельную тему ;)

                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Кстати, первое сообщение в теме - не Ваше, если уж на то пошло. Ваше - второе.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Просто я выделил это сообщение из другой темы :)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Цитата wind @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Цитата dleskov @
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Скажите, только без обид, здесь принята модерация темы создателем темы?

                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Нет, но желательно не оффтопить. Если хотите сравнить компиляторы delphi и c++ с компиляторами же java, создайте отдельную тему ;)

                                                                                                                                                                                                                                                                                                                                                                                                                                                                          По-моему, сравнивать надо реально доступные реализации. А то как-то нечестно получается.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                          В конце концов, HotSpot - тоже компилятор, только динамический. Кроме того, AOT-компиляторы Java есть, например, в IBM WebSphere Realtime и в ARM Jazelle.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            А потом уже поговорим - либо вы признаете свою неправоту, либо предложите лучший способ проверки.


                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Запускайте HotSpot JVM с ключиком -XX:+PrintCompilation и узнаете, какие именно методы были скомпилированы.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Кстати, а вы умеете подглядывать в код, сгенерированный JIT?


                                                                                                                                                                                                                                                                                                                                                                                                                                                                            Есть два варианта: 1. вариант извращенный с помощью дебаггера, 2. вариант нормальный с помощью -XX:+PrintOptoAssembly, которая поддерживается debug сборками JDK (доступны на dev.java.net)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Спасибо за подсказки, mr. Aleph.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              0 пользователей:


                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Рейтинг@Mail.ru
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              [ Script execution time: 0,5244 ]   [ 15 queries used ]   [ Generated: 13.07.25, 20:03 GMT ]