1. Куча / Говнокод #16340

    +126

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

    Милок сидит на досе и не умеет в gc.
    http://code-live.ru/post/cpp-pointers/

    Запостил: gost, 15 Июля 2014

    Комментарии (27) RSS

    • В каком-то бейсике для калькуляторов была похожая проблема.
      Ответить
    • Я нихуя не по--

      Какое, блядь, количество переменных в памяти? Или обьем памяти теперь меряется в переменных? "О, вчера купил плашку на 1024 переменных. " Что такое перегрузка системы? То есть если у меня была Винда она превратится Бубунту? Или это перезагрузка по Пидтерски ? Это у них там всякие сосули и гречи.
      Ответить
      • > Что такое перегрузка системы
        Ну когда система слишком сильно нагружена и от этого не работает.
        Ответить
        • То есть зависание. Но он указал зависание отдельно
          Ответить
          • Ну перегрузка это все же не совсем зависание.
            Ответить
            • Можно подробнее?
              Ответить
              • Ну всяко же видел, как работает комп, у которого 256 метров памяти, и при этом на нем назапускали кучу всякой ерунды, и он постоянно хрустит винтом и свопуется? Вот это, имхо, и есть перегрузка...
                Ответить
                • Это юзание файла подкачки с hdd. Ну да, ты прав.
                  Ответить
                  • Это настолько большое количество переменных, что они не помещаются в аппаратную часть.
                    Ответить
    • Кстати, он там пишет, что для того, чтобы не было "перегрузки", надо юзать "динамические переменные", а-ля указатели.

      int foo(int bar)
      {
          int *a = new int(42);
          return bar + *a;
      }
      
      int main()
      {
          int c = 0;
          for (int i = 0; i < 10000000; i++)
          {
              c = foo(43);
          }
      }


      vs

      int foo(int bar)
      {
          int a = 42;
          return bar + a;
      }
      
      int main()
      {
          int c = 0;
          for (int i = 0; i < 10000000; i++)
          {
              c = foo(43);
          }
      }


      Хто победит?
      Ответить
      • Ну может у него boehem gc подключен? ;)
        Ответить
      • А второй код компилятор скорее всего вообще выпилит нахрен..
        Ответить
        • С -O0 не выпилил, проверил.
          Ответить
          • разумеется, надо с -O3 пробовать
            Ответить
            • ВСка с /Ox проглотила и не подавилась, отожрав 533 мега памяти. Гцц под рукой не имеется.
              Ответить
              • Какая-то у ВСки ебанутая оптимизация -
                for (int i = 0; i < 10000000; i++)
                    {
                        foo(43);
                    }

                Нихрена не заоптимизировала, сожрала полгига.
                Ответить
              • вероятно, ты проверял первый код, а не второй, как говорил борманд.
                Ответить
                • Мнение gcc о втором коде:
                  main:
                          xorl    %eax, %eax
                          ret
                  Ответить
                  • А о первом?

                    udp, где-то видел сайт, который показывает выхлоп gcc, что-то вроде Ideone, только вспомнить никак не могу.
                    Ответить
                    • У первого есть побочные эффекты в виде утекающей ручьём памяти, его не оптимизируешь.
                      Ответить
                      • Угу, нашел тот сайт:

                        foo(int):
                        	pushq	%rbx
                        	movl	%edi, %ebx
                        	movl	$4, %edi
                        	call	operator new(unsigned long)
                        	movl	$42, (%rax)
                        	leal	42(%rbx), %eax
                        	popq	%rbx
                        	ret
                        main:
                        	pushq	%rbx
                        	movl	$10000000, %ebx
                        .L4:
                        	movl	$4, %edi
                        	call	operator new(unsigned long)
                        	subl	$1, %ebx
                        	movl	$42, (%rax)
                        	jne	.L4
                        	xorl	%eax, %eax
                        	popq	%rbx
                        	ret


                        http://gcc.godbolt.org, есличо.
                        Ответить
                        • А тут оптимизатор встроил в цикл код функции foo (заинлайнил), но утечка осталась. Хотя вручную код лечится от утечки легко:
                          int foo(int bar)
                          {
                              int *a = new int(42);
                              int result = bar + *a;
                              delete a;
                              return result;
                          }
                          Оптимизировать удалось, потому что код возвращает значение, а не указатель. При желании можно написать код, не поддающийся оптимизации:
                          int * foo(int bar)
                          {
                              int *a = new int(42);
                              *a = bar + *a;
                              return a;
                          }
                          Ответить
                          • > не поддающийся оптимизации
                            После инлайна получаится то же самое, что и с возвратом значения.
                            Ответить
                    • > А о первом?
                      А первый код не крестоидиоматичен. Надо как-то так:
                      int foo(int bar)
                      {
                          std::unique_ptr<int> a(new int(42));
                          return bar + *a;
                      }
                      Или так, если не дают свободы:
                      int foo(int bar)
                      {
                          std::auto_ptr<int> a(new int(42));
                          return bar + *a;
                      }
                      Ответить
      • Во втором коде return возвращает стек в исходное состояние, поэтому переполнения памяти не будет. Чтобы переполнить, нужно устроить рекурсию, например, так:
        int foo(int bar)
        {
            int a = bar + 1;
            if (a < 10000000) {
                a = foo(a);
            }
            return a;
        }
        Ответить
        • Это stack overflow будет, так не интересно.
          Ответить

    Добавить комментарий