1. C++ / Говнокод #14415

    +4

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    #include <iostream>
    using namespace std;
    
        void enable_misalignment_access_check(){
          cout<<"begin "<<__FUNCTION__<<endl;
          __asm__(
            "pushf\n"
            "orl $(1<<18),(%esp)\n"
            "popf\n"
          );
          cout<<"end "<<__FUNCTION__<<endl;
        }
    
    void alignedAccess(volatile unsigned char foo[])
    {
      cout<<"begin "<<__FUNCTION__<<endl;
      volatile int t = *(int *)(foo);
      cout<<"end "<<__FUNCTION__<<endl;
    }
    
    void unalignedAccess(volatile unsigned char foo[])
    {
      cout<<"begin "<<__FUNCTION__<<endl;
      volatile int t = *(int *)(foo+1);
      cout<<"end "<<__FUNCTION__<<endl;
    }
    
    unsigned char foo[] = { 1, 2, 3, 4, 5, 6 };
    
    int main(void)
    {
        alignedAccess(foo);
        unalignedAccess(foo);
        enable_misalignment_access_check();
        alignedAccess(foo);
        unalignedAccess(foo);
        return 0;
    }

    http://codepad.org/D6b5asES

    begin alignedAccess end alignedAccess 
    begin unalignedAccess end unalignedAccess
    begin enable_misalignment_access_check end enable_misalignment_access_check
    begin alignedAccess end alignedAccess
    begin unalignedAccess
    Bus error

    Запостил: LispGovno, 26 Января 2014

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

    • Умные сея гейдева наконец узнали что существует unaligned access и начали вырабатывать стратегию борьбы с этой напастью. Миллионы движков вдруг начали из-за этого тормозить и их пора переписывать.
      Ответить
      • Ну это еще надо постараться, чтобы у себя в коде замутить кривое выравнивание...

        Пока в голову приходят только #pragma pack(1) и извраты с кастами char* в указатели на что-то более крупное.
        Ответить
        • У них везде самописные контейнеры. Ты же видел контейнер Тараса. Они их понаписали чёртову кучу. Ты же знаешь что для движка всё что находится в STL - имеет фатальный недостаток.
          Ответить
          • ты так говоришь, как будто сам не гейдеятель
            Ответить
            • Да меня это бесит. Я хочу всех убить за их велосипедо строительство и свалить на хрен куда угодно.
              То, что ты сейчас увидишь - в этом тоже велосипеды виноваты (не дождались из-за великов):


              https://pp.vk.me/c540101/v540101687/9b20/l8cH679aVPY.jpg
              Ответить
          • А кстати и с самописным контейнером ты не запорешь выравнивание. gcc сделало вот так:
            struct foo {
                char buf[7];
            };
            // sizeof(foo) == 7, т.к. тут на выравнивания насрать
            
            struct bar {
                int x;
                char buf[3];
            };
            // sizeof(bar) == 8, чтобы в массиве из bar'ов х лежал аккуратно
            Ответить
            • Чего? оно разместило левый член char t; в моей структуре? Я думал кресты по стандарту в конец структур не дописывают мусор. Думал выравнивает только члены структуры, а на конец ей посрать и нужно выравнивать самому.
              Ответить
              • > Чего? оно разместило левый член char t; в моей структуре?
                Ты так говоришь, как-будто это что-то плохое.

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

                Кстати, а у вижуалки как с этим?
                Ответить
                • http://rise4fun.com/Vcpp/vnb
                  скимпилировалось без нареканий
                  Ответить
                • То есть можно писать в buf[3], ведь по теории там дырка.
                  Ответить
                  • Ага, хранить секретные данные в паддинге, чтобы враг не догадался.
                    Ответить
                • > А в стандарте этот момент я не читал...

                  Этот момент описывается не в крестах. Это имплементэйшн дефайнед - другими словами "ABI".
                  Ответить
                  • Ну то есть нифига на это рассчитывать нельзя?
                    Ответить
                    • почти все архитектуры (за исключение сильно извратных встроенных) следуют юниховым соглашениям и поддерживают как минимум естественное выравнивание: адрес переменной кратен её размеру; размер структуры выравнивается (structure is padded) на размер самого большого примитивного типа в ней содержащегося; стандартные функции выделения памяти возвращают блок, адрес которого пригоден для любого примитивного типа.
                      Ответить
          • > Ты же знаешь что для движка всё что находится в STL - имеет фатальный недостаток.

            Мои велосипеды не имеют аналогов в STL. Вернее, один имеет, но только в STL сипипоха, а не в моём.
            Ответить
            • Ты так говоришь, как-будто я про тебя.
              Ответить
            • Гагага. Почитал тему дальше.

              Hardcode успокоился, TarasB прилёг рядом с ним, и так вместе они читали стандарт языка. Последним остался Kartonagnick. У него вдруг подогнулись ноги, и он рассердился на себя.
              — Неслыханно, — пробурчал Kartonagnick. — TarasB знает кресты, а Kartonagnick боится!
              С этими словами он перелистнул страницу стандарта. Но ему показалось, что голова у него стала чугунная, и охватила его такая тьма, что даже он, Kartonagnick, без страха измеривший глубочайшие подвалы языка, вдруг попросил всё это развидеть.


              Это намек на то, что Тарас знает кресты или намек на то, что Хардкод - кавказец? А насколько у него жесткий?

              Что-за цитата? Я со школы ничего не читал.
              Ответить
              • сам написал, сам поржал
                Ответить
                • сам удалил пост, сам отругал админов за то что удаляют, сам себя забанил за обсуждение админов
                  Ответить
                  • Вспомним, что из этого уже реализовано без правки исходников ГК:
                    1. Сам удалил пост — можно попытаться уложиться в лимит времени на редактирование.
                    2. Сам отругал админов — пишешь красным от имени админа причину удаления, потом пишешь ответ.
                    3. Сам себя забанил — сменил пароль.

                    Ну вроде всё возможно.
                    Ответить
                    • шизофрения
                      Ответить
                      • Для полного счастья надо ещё от имени мульта написать, мол, так тебе и надо, что тебя забанили, а потом другим мультом написать, что жаль, хороший был юзер...
                        Ответить
                        • я потом вериги одеть и плеткой, плеткой...
                          Ответить
                • ЕМНИП, это из "Хранителей" Толкина, сцена спуска в Морию.
                  Ответить
    • Кстати у меня на 64 битной линухе этот код падает с bus error прямо на cout<<"end "<<__FUNCTION__<<endl в enable_misalignment_access_check :)
      Ответить
      • Что это? Ошибка в коде библиотеки или код выше то ещё дерьмо?
        Ответить
        • Походу в данной реализации stl где-то забили на выравнивания ;(

          Сейчас попробую крешдамп собрать и посмотреть на него.
          Ответить
          • Если верить крешдампу, то оно упало в __memcpy_sse2.
            Ответить
            • попробуй на границу параграфа выровнять буфер и скопировать через __memcpy_sse2.
              через std::align выровнять можно буфер заведомо большего размера
              Ответить
              • > std::align
                А нету :(

                Да там питушня полнейшая. Можно даже ничего не выводить, тупо включить AC и выйти. После чего сразу же пидорасит кишки libc с тем самым bus error...

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

                P.S. А вот на ARM'овских линухах таких проблем быть не должно, там то поди все выравнивания вылизаны.
                Ответить
                • > А нету :(
                  Может тогда компилятор староват? Они небось пока в стандарт не ввели С++11, то о выравнивании не сильно заботились. Может ключики нужно указать на выравнивание? А вообще гейдевовцы обычно VirtualAlloc вызывают, что бы на границу параграфа (16 или сколько там нужно для ссе) было выравнено. В линуксе должно быть похожее. Кстати, за это тоже хочется убить.
                  Ответить
                  • Да у обычного malloc'а вроде бы тоже достаточное для всех хардварных типов выравнивание...

                    Там походу какое-то горе от ума, ибо тот же __memcpy_sse2 падает не на sse'шной команде, а на вполне безобидном в обычном режиме муве: mov (%rsi), %ecx
                    Ответить
                  • Самый лол в том, что memcpy даже теоретически невозможно сделать эффективным и alignment-safe одновременно.

                    Либо программист отвечает за alignment'ы входного и выходного буфера, либо придется копировать по одному символу (можно, конечно, в ряде случаев копировать по 4 или по 8 вместо 16, но производительность будет уже не та...), либо насрать на выравнивания, и делать так, как это сделано сейчас ;(
                    Ответить
                    • копируешь байт, потом 2, потом 4, потом 8 через sse целой группой, потом 4, потом 2, потом 1
                      Это худший случай.
                      Ответить
                      • Авотхуй. Это прокатит если взаимное расположение буферов удачное: разность между их адресами кратна 16.

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

                        А сейчас на x86 и x86_64 сделано довольно тупо - копируется байт, потом два и т.д. до 8, пока размер копируемого блока не выровняется на 16, а дальше идет блочное копирование (насрав на alignment).
                        Ответить
                        • То есть ты хочешь сказать или выравнен один буфер или второй? Но оба сразу почти никогда? Вот это номер... Я никогда не задумывался об этом...
                          Ответить
                          • > Но оба сразу почти никогда?
                            В одном случае из 16, если об этом не позаботились заранее ;)
                            Ответить
                            • Кстати, для AVX и SSE нужно выравнивание 16? Я не ошибся?
                              Ответить
                              • Ну в sse регистры по 128 бит, а в avx по 256, получается, что для эффективногоо avx-копирования желательно выравнивать аж на 32...

                                Требоваться то оно не требуется, но с выравниванием всяко будет быстрее, меньше кешлайнов затронет и т.п...
                                Ответить
      • ESP на RSP заменил? У меня после такой замены на FreeBSD заработало .
        Ответить
        • Конечно, без такой замены - тупо сегфолт.

          Да здесь в memcpy и его друзьях дело. Походу 128 битные загрузки/сохранения даже в невыровненном виде быстрее чем побайтовое копирование. Поэтому libc'шники на x86 и x86_64 и пожертвовали alignment'ом.

          P.S. У фряхи же вроде своя сишная либа, не libc?
          Ответить
    • Надо бы и мне свой контейнер подровнять.
      Ответить
    • День 1:
      Я заведу тип {char; T} и разберу случаи равнения на 1,2,4. На остальные пока выдам ошибку компиляции. Мне хватит этого на первое время, но ненадолго. Надеюсь, что вскоре за мной придёт помощь.
      Ответить
    • Ух ты, мой код поклали. Говна не вижу.
      Ответить
      • так свой код не пахнет
        Ответить
        • Просто проверка включена для надежности. Что тут может пахнуть?
          Ответить
          • успокойся, все хорошо. я уже ухожу
            Ответить
          • > для надежности
            Как было показано выше по треду - первый же memcpy развалит всю эту надежность к хуям. Т.к. невозможно сделать одновременно быстрый и alignment-safe memcpy. Если memcpy работает с AC - значит он копирует все по одному байту, или тебе просто повезло, и оба буфера были хорошо выровнены (что при копировании строк не с начала и их конкатенации - просто случайность).

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

                А если тупо потестить свой контейнер на наличие проблем с выравниванием - почему бы и нет.
                Ответить
                • А кто предлагал её использовать в продакшене? Лишний повод у релиза упасть - не нужен.
                  Ответить

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