1. Си / Говнокод #16854

    +133

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    8. 8
    9. 9
    if (strcmp(request_name, REQUEST_1) == 0)
                function_1();
            else if (strcmp(request_name, REQUEST_2) == 0)
                function_2();
            else if (strcmp(request_name, REQUEST_3) == 0)
                function_3();
            /* И так далее */
            else if (strcmp(request_name, REQUEST_N) == 0)
                function_n();

    Собственно, как можно ЭТО рефакторить в более приемлемый вид и можно ли заменить на branchless?

    Запостил: codemonkey, 15 Октября 2014

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

    • Переписать на PHP, потому что в PHP есть ассоциативные массивы:
      $jump_table = array(
        REQUEST_1 => 'function_1',
        REQUEST_2 => 'function_2',
        REQUEST_3 => 'function_3',
        REQUEST_N => 'function_n'
      );
      
      ...
      
      $jump_table[$request_name]();

      http://ideone.com/lXDlZG
      Ответить
      • А в Си чтоли нет ассоциативных массивов? :)
        Ответить
        • Да в Си сплошные суррогаты. Там даже массивы индексировать не с нуля нельзя, да и вообще работа с массивами перепутана с арифметикой указателей. То ли дело PHP...
          Ответить
          • на идеологичекском уровне, я предпочитаю реализацию массивов в лиспе. потому что там даже массив - список.
            Ответить
        • показать все, что скрытоvanished
          Ответить
    • свич по первой букве, потом иф
      Ответить
      • Можно для этого какой-нибудь lex запользовать, он сам switch/if сгенерит
        Ответить
        • Можно проще: заранее посчитать CRC32 всех констант типа REQUEST_N, потом заполнить таблицу переходов, а потом делать вызов по адресу jump_table[CRC32(request_name)]. Так обойдёмся и без ифов, и без свитчей, и без ассоциативных массивов.
          Ответить
          • Если считать хеш-таблицу как подвид ассоциативного массива...

            К тому же будет очень весело если придёт неизвестный request_name. Придётся всю остальную таблицу забивать указателями на void nop(){}
            Ответить
          • CRC16 может быть? Или реально jump_table на 16-32 гига?
            Ответить
          • > jump_table[CRC32(request_name)]
            Табличка размером в 32 Гб (на 64-х битных архитектурах). Мсье знает толк.
            Ответить
            • Ну учитывая, что системы обычно выделяют память лениво, можно сделать mmap на 32 гига указателей, а потом его заполнить. В худшем случае это потребует N * PAGESIZE + C, где C - некий предварительно выделяемый объем памяти.

              Другое дело, что если пользователи будут присылать некорректные запросы, будут происходить промахи, и память будет выкушиваться, что ведет потенциально к DoS.
              Ответить
              • > можно сделать mmap на 32 гига указателей

                mmap() не нужен. malloc()ова память на линухе (и многих *нихах) тоже ленивая. и с высокой вероятностью malloc(32GB) либц сама догадается mmap()ом сделать.

                > что ведет потенциально к DoS.

                по моему опыту либо ОСь либо аппликуха повалится просто (oom killer). что как бы и есть недостаток ленивого выделения физической памяти: у какого `a = b;` возврат ENOMEM не предусмотрен.
                Ответить
                • > либо ОСь либо аппликуха повалится просто
                  Дык это и есть Denial of Service :)

                  Кстати, по опыту - перед падением всяко будет еще большой интервал с дикими тормозами... У меня проги, решившие сожрать много памяти, до OOM обычно не доживали. Я первым тыкал в reset, ибо ничего другого не оставалось.
                  Ответить
                  • > перед падением всяко будет еще большой интервал с дикими тормозами...
                    Не обязательно. Когда выделяется память (в Solaris по крайней мере), она резервируется в т.н. Swap Space, составленном из дискового свопа и незанятой разными невыгружаемыми вещами оперативной памяти, что позволяет гарантировать, что данные можно будет хотя бы куда-нибудь положить (и поэтому не возникает ENOMEM).

                    Другое дело, что когда все 32 Гб начинают активно использоваться, разница в скорости обращения к диску и памяти начинает сказыватся. Кроме того, начинают включатся всякие механизмы троттлинга выделения страниц.

                    В нашем случае скорее всего все некорректные страницы памяти (не содержащие корректные jump_table[CRC32(request_name)]) скорее всего вытеснятся на диск, и DoS может и не случится :)
                    Ответить
                    • Как ни странно, на Linux это работает и не вызывает DoS. Для чтения там используется специальная zero-page, которая, как я понял одна на всю систему:

                      static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
                      		unsigned long address, pte_t *page_table, pmd_t *pmd,
                      		unsigned int flags)
                      {
                      ...
                      
                      	/* Use the zero-page for reads */
                      	if (!(flags & FAULT_FLAG_WRITE)) {
                      		entry = pte_mkspecial(pfn_pte(my_zero_pfn(address),
                      						vma->vm_page_prot));
                      		page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
                      		if (!pte_none(*page_table))
                      			goto unlock;
                      		goto setpte;
                      	}


                      Так что все что нужно - это 32 Гб своп-файл.
                      Ответить
                    • > Кроме того, начинают включатся всякие механизмы троттлинга выделения страниц.
                      И мне про троллинг страниц вконтакте расскажите.
                      Ответить
                  • Это да, когда винде не хватает памяти, она нахер виснет. Чтобы вызвать диспетчера задач, я должен делать это через те же ебучие тормозные абстракции, общие для всех приложений. Кнопки "остановить всё нахуй и выбрать кого ёбнуть", работающей на уровне прерываний, в винде нет, и это меня просто пиздец как бесит. Даже жизненно необходимые инструменты сделали через тормозную ебучую хуйню с низшим приоритетом блять уебни.
                    Ответить
                    • Если открыта сосноль, то можно попытаться выполнить taskkill... Но taskkill — это обычный процесс, обычная тормозящая питушня.
                      Ответить
                    • Причем в семерке alt-ctrl-del переключает на отдельный десктоп, где нужно выбрать пункт "диспетчер задач". Вот, казалось бы, сделайте еще один шаг, покажите диспетчер прямо на этом экране... Можно было бы спокойно убивать всяких винлоков... Ну и, как дополнение, вообще остановить все таски, помимо диспетчера...

                      Но нет, M$ как всегда запороло хорошую задумку - менюха для вызова диспетчера на отдельном столе, а сам диспетчер - на обычном. Из-за чего он почти бесполезен.
                      Ответить
                      • Ctrl+Shift+Esc
                        Ctrl+Shift+F1 c anvir, что бывает побыстрее
                        Ответить
                        • Так та же самая тормозная питушня и вызывается. Ждёшь его несколько минут, потом выскакивают сразу десять диспетчеров задач.
                          Ответить
                        • Да знаю я про Ctrl+Shift+Esc. Только вот абстрактный менеджер трёкнопочных сочетаний находится в ожидании того, когда же память таки выдадут процессу.
                          Ответить
                        • Грёбаный Хром — самый газообразный веб-браузер в мире! Только что решил его запустить в исследовательских целях. Результат превзошёл все ожидания — у меня раньше даже Фаерфокс и ИЕ так не тормозили.

                          После того, как Хром сожрал все ресурсы, стала тормозить даже мышь. Нажал Ctrl+Shift+Esc — окно появилось минут через десять. Сначала боролся с процессами Хрома, как с головами Гидры, но в итоге всё свелось к...
                          taskkill /IM chrome.exe /F
                          Ответить
                          • В прошлом году заметил что с каждым увеличением версии хрома на десять его потребление памяти примерно удваивается.
                            Прям следствие закона Мура какое-то.
                            Ответить
                            • Зато у них ЛГБТ уважают!
                              Ответить
                              • Да я постоянно ругаюсь когда это говно жрёт память и крашится: "Ну какой пидарас это написал?!".
                                А там может и вправду пидарасы. Вот думаю даже не оскорбительно как-то получается.
                                Ответить
                                • Среднестатистический россиянин не в состоянии подобрать слов для оскорбления гомосексуалистов...
                                  Ответить
                      • M$ идиоты, что тут сказать.
                        Ответить
                      • менюха на отдельном столе чтобы ее враг не спиздил, примерно по той же причине, по какой там винлогон.

                        Теоретически ты можешь запустить powershell и там Stop-Process, но это всё равно жутко томрозит, и вероятно там не джинтуный .net внутри

                        Правильное решение это как в никсах-иксах: CTRL+ALT+FN переносит тебя на виртуальную косноль с запущенным на ней виртуальным терминалом.
                        Написать там kill стоит в миллион раз меньше ресурсов, чем ебля с гуем и кнопочками
                        Ответить
                    • > когда винде не хватает памяти, она нахер виснет
                      В линухе, на самом деле, еще хуже. В винде я обычно всё же умудрялся убить процесс. В линухе же почти всегда working set > physical memory = мучительная смерть. Даже при 8 гигах оперативы.
                      Ответить
                      • А на OpenVZ?
                        Ответить
                        • Х.з., я не юзал.

                          P.S. Кстати, вот то ли у меня руки такие кривые, то ли в ядре нет нормального планировщика i/o... Кучу манов и советов перечитал, но i/o лаги во время копирования больших файлов так и не удалось устранить.
                          Ответить
                          • Кстати, что Вы думаете о http://govnokod.ru/16862#comment251476?
                            Ответить
                            • Зачем вы пишете в запомоенных тредах?
                              Страйкер потом потрёт, и всё.
                              Ответить
                              • Так и хорошо, что потрёт. Кому нужны через джва года временные обсуждения бесконечного стока со ссылками на посты на форуме со ссылками на файлы на rghost, которые могут быть удалены, которые могут быть удалены?
                                Вот "Посоны, я запилил бесконечный сток" надо вынести в отдельный тред и попросить Люра поставить ему +1000.
                                Ответить
                                • можно на gvforum.ru (на правах рекламы)
                                  Ответить
                                  • На gvforum.ru тоже нужен сток. Последние темы слишком быстро уходят. Обновляешь страницу раз в неделю, а там как будто ничего не писали.
                                    Нельзя просто так взять и узнать, что там что-то изменилось. Возможно, это одна из причин, по которой туда не пишут.
                                    Ответить
                                  • Вот я недавно, например, о баге писал туда: http://gvforum.ru/viewtopic.php?pid=2174#p2174. Может, Вы тихо его пофиксили или уже знали про него, а может просто сообщения не видели, поскольку тред быстро скрылся.
                                    Ответить
                                • В данной ситуации можно выкрутиться квадратными смысловыми скобками, чтобы это можно было прочитать, но на слух это не воспримется вообще, поэтому в живых языках есть ограничение на вложенность, которое ты нарушил.
                                  Ответить
                                  • > ограничение на вложенность

                                    Я на цыпочках, как вор,
                                    Пробираюсь, чуть дыша,
                                    Чтобы не спугнуть
                                    Тех, кто спит уже давно,
                                    Тех, кому не всё равно,
                                    В чью я комнату тайком
                                    Желаю заглянуть,
                                    Чтобы увидеть,
                                    Как бессонница в час ночной
                                    Меняет, нелюдимая, облик твой...


                                    Что там нарушил 1024--?
                                    Ответить
                                    • Ок, можно делать глубокую вложенность, если после вложения не идёт выход на вложение меньшего уровня.
                                      Ответить
                                      • >делать глубокую вложенность, если после вложения не идёт выход на вложение меньшего уровня.
                                        А если ИСКЛЮЧЕНИЕ из правила?
                                        Ответить
                                • Кстати я тут придумал как технично отсечь идиота, не тронув при этом адекватов.
                                  text-decoration:underline; text-decoration:line-through;
                                  Ну вы поняли.
                                  Ответить
                                  • Ох, долго же искал я http://govnokod.ru/16084#comment234194, а оказалось, что там это не сразу применяется к одному и тому же тексту.
                                    Ответить
                                  • Можно намутить что-нибудь на CSS4: http://www.w3.org/TR/selectors4/#subject А нет, не нужно, его же не поддерживают браузеры. Кто-то даже от отсутствия поддержки CSS3 страдает.
                                    Ответить
                              • Ну как, потёр?
                                Ответить
                                • А вот у нас на https://gcode.space ничего не потёрто!
                                  Ответить
                          • выбирай https://wiki.ubuntu.com/Kernel/Reference/IOSchedulers
                            Ответить
                    • Я в своё время хотел аппаратную кнопку для его вызова какими-то отдельными от системы средствами.
                      Но с тех пор памяти у меня стало в 16 раз больше. А файл подкачки на SSD. И потревожит тут только большой х** на весь экран, а диспетчер задач открывается даже, если процессор полностью занят (не знаю, это заслуги новой винды или у процессоров теперь ещё есть ресурсы при формальной 100% загрузке).
                      Ответить
                      • Вы боитесь большого указателя на указатель на весь экран? Да, я тоже боялся этого заката Солнца вручную, потому что даже массив массивов выглядит интуитивнее.
                        Ответить
                  • показать все, что скрытоvanished
                    Ответить
              • я думаю что надо просто поставить пачку серваков, и каким кластером распределенную память сделать.
                Ответить
          • после прыжка всё равно делать проверку надо, мало ли это другая строка с той же контрольной суммой
            Ответить
            • Самое плохое, что тут могут быть два варианта:
              1. Столкновение с известным значением параметра. Это можно предусмотреть ещё на этапе разработки, сделав ветвление для того значения хеша, которому соответствуют несколько допустимых значений параметра.

              2. Столкновение с неизвестным значением. Если нужно отфильтровать и такие случаи, то с этим ничего не поделать, придётся на входе в каждую функцию проверять значение параметра на точное совпадение с ожидаемым.
              Ответить
            • показать все, что скрытоvanished
              Ответить
      • нет. намного эффективней будет распаралелить сравнения. сделать Н прог, каждая из которых производит сравнение с заданой строкой. запустить в бэкграунде эти проги - а потом просто проверить какая програ завершилась успешно! энтэрпрайз!!
        Ответить
    • -
      Ответить
    • Если сигнатуры функций одинаковы - можно массив структур хуйнуть: http://ideone.com/8hfLhh
      Если разные - положить болт, пока профайлер не начнет кудахать.
      Ответить
    • показать все, что скрытоМой твердый оплетённый венами вулкан судорожно сокращаясь выбрасывает из себя липкую тёплую влагу. Её много.
      Ответить
    • Посаны, какую либу для сишки взять как замену STL по алгоритмам и структурам данных? У меня бугурт. Реально.
      Ответить
      • Всякие clibы, glibы, но без шаблонов оно не то.
        Ответить
        • Да всё то. В сишке указатель на любую хрень превращается в указатель на любую другую хрень. Что правда источник батхерта у одних и источник не описуемого счастья у других.

          > без шаблонов оно не то.
          А главное без лямбд. Написать свои правда с gnu экстеншен можно
          Ответить
          • >Что правда источник батхерта у одних и источник не описуемого счастья у других.
            Так это извечный срач. Одни любят динамически типизируемые языки, другие - нет.

            >А главное без лямбд.
            Невелика потеря. Указатели на фукнцию.
            Ведь это очень старый приём, например для сортировки возвращать указатель на функцию-компаратор.
            Ответить
        • клиб я не нашел и первый раз слышу (бан в гугле).
          глиб - монструозный буст из гнома, в основном системные фичи (он под винду хоть работает?)
          Ответить
          • g_list_append ()
            ах глисты вы мои глисты растянулись на пол версты
            Ответить
      • показать все, что скрыто-
        Ответить
      • http://libcello.org/
        Ответить
        • Мои глаза!
          var prices = new(Table, String, Int);
            put(prices, $(String, "Apple"),  $(Int, 12)); 
            put(prices, $(String, "Banana"), $(Int,  6)); 
            put(prices, $(String, "Pear"),   $(Int, 55));
          но круто.
          Ответить
        • Круть. Даже не верится что такое на сишке замутили.
          Но мне кажется исключения и все остальные полезные фичи в крестах будут работать быстрее. Ибо тут препроцессор, а сколько говна он добавит одному бусту богу известно.
          Ответить
        • Да это же... ЖУКВЕРИ!!!
          Ответить
      • > У меня бугурт. Реально.
        Ты это, поосторожнее. А то сегодня бугурт, а завтра создаёшь ещё один язык в дополнение к крестам, obj-C, Swift...
        Ответить
    • Ответить
      • З̶̲а̶̲ч̶̲е̶̲м̶̲?̶̲
        Ответить
        • А⃤ я⃤ е⃤щ⃤ё⃤ т⃤а⃤к⃤ м⃤о⃤г⃤у⃤.⃤ И͜ д͜аж͜е т͜ак͜.
          Ответить
          • >З̶̲а̶̲ч̶̲е̶̲м̶̲?̶̲
            Хе-хе. Так в социальных сетях где нет разметки делают.
            Тест скрипта.
            >А⃤ я⃤ е⃤щ⃤ё⃤ т⃤а⃤к⃤ м⃤о⃤г⃤у⃤
            Вот это у меня не показывает нормально.
            Ответить
          • * g o a t * g o a t * g o a t * g o a t *
            g                                       g
            o           ___.                        o
            a          //  \\                       a
            t         ((   ''                       t
            *          \\__,                        *
            g         /6 (%)\,                      g
            o        (__/:";,;\--____----_          o
            a         ;; :';,:';`;,';,;';`,`_       a
            t           ;:,;;';';,;':,';';,-Y\      t
            *            ;,;,;';';,;':;';'; Z/      *
            g            / ;,';';,;';,;';;'         g
            o           / / |';/~~~~~\';;'          o
            a          ( K  | |      || |           a
            t           \_\ | |      || | valkyrie  t
            *            \Z | |      || |           *
            g               L_|      LL_|           g
            o               LW/      LLW/           o
            a                                       a
            t                                       t
            * g o a t * g o a t * g o a t * g o a t *
            Ответить
            • О Боже, ВИН!
              Сделал мой вечер.Я думал об таком когда-то.
              Ответить
            • Слава Тангниостру! Тангрисниру слава! Кто скачет, тот Слейпнир!
              Ответить
              • У меня goatsex всегда ассоциировалось не с известной картинкой, с совокупляющимся козлами, но лениво было время тратить на такую псевдографику.
                Кстати говорят недавно запустили Goatse Coin. Конардо на пути к мировому господству.
                Ответить
                • Можно взять с http://www.ascii-art.de/ascii/ghi/goat.txt какого-нибудь козла и пристроить к нему старого козла, который в самом низу страницы.
                  Ответить
                  • function image(txt){
                      return txt && txt.replace(/\t/g, '        ').split(/[\r\n]{1,2}/);
                    }
                    
                    function shiftX(img, x){
                      if(x > 0){
                        var pixels = Array(x+1).join(' ');
                        return img.map(function(line){ return pixels + line; });
                      }
                      
                      if(x < 0) return img.map(function(line){ return line.substr(-x); });
                      return img;
                    };
                    
                    function shiftY(img, y){
                      return y > 0 ? Array(y).join('*').split('*').concat(img) :
                             y < 0 ? img.slice(-y) : img;
                    };
                    
                    function shift(img, x, y){
                      return shiftY(shiftX(img, x), y);
                    };
                    
                    function width(img){
                      return Math.max.apply(Math, img.map(function(line){ return line.length; }));
                    };
                    
                    function height(img){
                      return img.length;
                    };
                    
                    function mix(i1, i2){
                      var w = Math.max(width(i1), width(i2));
                      var h = Math.max(height(i1), height(i2));
                      var lines = [];
                      
                      for(var y=0; y<h; ++y){
                        var fst = i1[y], snd = i2[y];
                        if(!fst && !snd) lines.push('');
                        else if(!fst) lines.push(snd);
                        else if(!snd) lines.push(fst);
                        else {
                          var line = '';
                          for(var x=0; x<w; ++x){
                            var f = fst.charAt(x), s = snd.charAt(x);
                            if(!f && !s) line += ' ';
                            else if(!s) line += f;
                            else if(!f) line += s;
                            else line += s === ' ' ? f : s;
                          }
                          lines.push(line);
                        }
                      }
                      
                      return lines;
                    };
                    
                    function string(img){
                      return img.map(function(line){ return line.replace(/\s+$/g, ''); })
                        .join('\n').replace(/\n+$/, '');
                    };
                    
                    function wall(w, h, e){
                      return image(Array(h+1).join('x').replace(/x/g, Array(w).join(e) + '\n'));
                    }
                    
                    var goat = image("\
                     _))\n\
                    > *\\     _~\n\
                    `;'\\\\__-' \\_\n\
                       | )  _ \\ \\ ejm97\n\
                      / / ``   w w\n\
                     w w\n"),
                    w1 = mix(shiftY(wall(60, 1, '░'), 7), wall(30, 8, '░')),
                    w2 = wall(15, 8, '░');
                    
                    var i = -100;
                    setInterval(function(){
                      if(i < -10) i = 40;
                      document.body.innerHTML = '<pre>' +
                        string(mix(mix(w1, shift(goat, --i, i*i % 2)), w2)) + '</pre>';
                    }, 100);
                    Ответить
                    • var oldGoat = shiftY(image("X /)  (\\\r\n )\\.:::::::::./(\r\n \\( oX  o )/\r\n   '-./ / _.-'`-.\r\n    ( oo  ) / _  \\\r\n    |'--'/\\/ ( \\  \\\r\nX\\''/  \\| \\ \\  \\\r\nX ww   |  '  )  \\\r\nXX |.' .'   |\r\nXX.' .'==|==|\r\nX    / .'\\    [_]\r\nX   (/\\) |X/\r\nX   \"\"\"'/|    |\r\nXX / |    |\r\nXX|  |    |\r\nXX|__|___/\r\nXX[__[___]\r\nX   .-'.-'  (\r\nX  (__(__.-._) LGB".replace(/X/g,'     ')), 5);
                      var goat = shiftY(image("X___.\n    //  \\\\\n   ((   ''\n    \\\\__,\n   /6 (%)\\,\n  (__/:\";,;\\--____----_\n   ;; :';,:';`;,';,;';`,`_\nX;:,;;';';,;':,';';,-Y\\\nX ;,;,;';';,;':;';'; Z/\nX / ;,';';,;';,;';;'\nX/ / |';/~~~~~\\';;'\n    ( K  | |X || |\nX\\_\\ | |X || |X valkyrie\nX \\Z | |X || |\nX    L_|X LL_|\nX    LW/X LLW/".replace(/X/g,'     ')), 8);
                      var censored = shift(wall(10, 3, '█'), 4, 15);
                      var eye = [' ', 'o', '-'].map(image);
                      var gtext = "* g o a t s e x * g o a t s e x * g o a t s e x *";
                      var gl = gtext.length - 1;
                      var ghor = image(gtext);
                      var gver = image(gtext.replace(/\s/g, '\n'));
                      var frame = mix(ghor, mix(shiftY(ghor, gl/2), mix(gver, shiftX(gver, gl))));
                      function mixArray(imgarr){ return imgarr.reduce(mix); }
                      var pointer = shiftX(image('Konardo\n   |\n   v'), 4);
                      var x = 25, d = 1, s = 8, y = -25;
                      setInterval(function(){
                        x == 25 && s > 0 ? --s : x > 16 ? --x : x += d = -d, y < 5 && ++y;
                        document.body.innerHTML = '<pre>' +
                          string(mixArray([
                            goat,
                            shiftX(mix(oldGoat, shiftX(censored, d < 0 | 0)), x),
                            shiftY(pointer, y),
                            frame,
                            shift(eye[s % 2 + (s > 0)], 29, 7)
                          ])) + '</pre>';
                      }, 300);

                      // Требует функции из комментария выше.
                      Ответить
                      • Лол, Два неловких поворота, И козёл ебёт ФедотаКонардо.
                        Ответить
                        • два неловких поворота, и из твоей жопы хлынет кровь.
                          Да, и в носу не ковыряй - плохая примета ;)
                          Ответить
            • показать все, что скрытоvanished
              Ответить
        • На ванишед ответил.
          Ответить
    • показать все, что скрытоvanished
      Ответить

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