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

    +1

    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
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    // https://github.com/CVC4/CVC4/blob/14b9dbaa0c9e8dce52d1a28595dc1cc80756abed/src/expr/pickler.cpp
    
    
    static Block mkBlockBody4Chars(char a, char b, char c, char d) {
      Block newBody;
      newBody.d_body.d_data = (a << 24) | (b << 16) | (c << 8) | d;
      return newBody;
    }
    
    static char getCharBlockBody(BlockBody body, int i) {
      Assert(0 <= i && i <= 3);
    
      switch(i) {
      case 0: return (body.d_data & 0xff000000) >> 24;
      case 1: return (body.d_data & 0x00ff0000) >> 16;
      case 2: return (body.d_data & 0x0000ff00) >> 8;
      case 3: return (body.d_data & 0x000000ff);
      default:
        Unreachable();
      }
      return '\0';
    }
    
    // ...
    
    void PicklerPrivate::toCaseString(Kind k, const std::string& s) {
      d_current << mkConstantHeader(k, s.size());
    
      unsigned size = s.size();
      unsigned i;
      for(i = 0; i + 4 <= size; i += 4) {
        d_current << mkBlockBody4Chars(s[i + 0], s[i + 1],s[i + 2], s[i + 3]);
      }
      switch(size % 4) {
      case 0: break;
      case 1: d_current << mkBlockBody4Chars(s[i + 0], '\0','\0', '\0'); break;
      case 2: d_current << mkBlockBody4Chars(s[i + 0], s[i + 1], '\0', '\0'); break;
      case 3: d_current << mkBlockBody4Chars(s[i + 0], s[i + 1],s[i + 2], '\0'); break;
      default:
        Unreachable();
      }
    
    }

    Очередное переизобретение какой-то байтоебской поеботы типа ntohl(). И вообще, тут UB.

    Запостил: j123123, 21 Февраля 2019

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

    • Hakuna matata! В программах на "Си" или "C++" всегда есть какой-нибудь UB.
      Ответить
    • А где, собственно , UB?

      P.S. s.size() >= std::numeric_limits<unsigned>::max() - 4 наверняка вылетит по памяти значительно раньше. Но "cover my ass" assert можно и вставить.
      Ответить
      • Ну, к примеру, на шестой строке.
        Ответить
        • Надо заранее указать тип контейнера для результата, чтобы не было переполнения, иначе тупой компилятор может попытаться сдвинуть char на 24 разряда?

          Что-то типа (uint32_t)a << 24 или static_cast?
          Ответить
          • Не, char он таки превратит в int перед сдвигом.

            Но int во-первых хуй знает какого размера. А во-вторых сдвиг знакового числа влево до упора ничем хорошим не закончится (даже при 32-битном инте).
            Ответить
            • У d_data и у char знаковость разная?
              Ответить
              • Это уже не важно.
                Ответить
                • А что важно?

                  UB существует только в «C» и «C++». В других языках программирования никаких UB нет, именно поэтому я за другие языки.
                  Ответить
                  • > что важно
                    1) число знаковое и может быть отрицательным
                    2) его двигают влево
                    Ответить
                  • > UB существует только в «C» и «C++»
                    "UB" существует во всех низкоуровневых языках с претензией на переносимость и у которых больше одной реализации. Даже у разных процов линейки "x86" в некоторых ситуациях было разное поведение на разных процах (щас точно не помню все, помню что была хуита с чтением слова по адресу FFFF, в одних процах байт читался из следующего сегмента, в других из начала текущего, остальных нагуглить/наяндексить не могу, они советуют мне посмотреть "Свойства системы"), так в стародавние времена определяли на каком проце мы запущены.
                    Ответить
                    • Когда на одном проце так, а на другом по-другому - это implementation defined. С этим можно жить.

                      UB хуже. С ним даже доки по железу и конпелятору тебе не помогут.

                      И, на самом деле, UB есть и во вполне высокоуровневых языках. Просто они там довольно очевидные. Гонки между потоками, к примеру.
                      Ответить
                    • > у разных процов [...] было разное поведение на разных процах
                      Мда, надо бы как-нибудь выделить денёк, чтобы выспаться.
                      Ответить
                    • > низкоуровневых языках
                      А уж в железе сколько UB'ов...
                      Ответить
                      • а уж в аналоговом железе...
                        Ответить
                        • Открою секрет: цифровое железо –— это абстракция. В любом железе хоть на какое-то время появляются сигналы, уровень которых между нулём и единицей.

                          В первых пятивольтовых микросхемах ТТЛ входной сигнал в интервале от 2,5 вольт до 5 воспринимался как единица, от 0 до 0,5 вольт –— как ноль, а вот сигнал в интервале 0,5...2,5 вольт был UB.
                          Ответить
                          • Именно поэтому поверх этой абстракции навернули ещё одну - синхронную логику, где все триггеры переключаются одновременно (более-менее).
                            Ответить
                          • З.Ы. А на границе синхронного домена стоят многослойные синхронизаторы, которые пытаются не пустить UB внутрь...
                            Ответить
            • А поместицца ли в int гугол?
              Ответить
              • На этот вопрос легко ответить - это undefined behavior.
                Ответить
              • В "Python" да. Именно поэтому я за "Python".
                Ответить
                • и в руби тоже
                  тока он там переключица в Bignum или как оно тмм
                  Ответить
                • в третьем пиздоне да
                  а во втором Int и long были разными тупами с программным переключеним
                  потом стал PEP237

                  забавно что было такое предложегие: сделать union в котором лежит long (для инта) или массив из digit (для longа) на пару с long size;

                  отличалось по последнему биту: им пожертвовали ради совмещения.
                  соответствено sizeof врал, надо было проверять последний бит, и если он 1 то брать size.

                  к щастью, это говнорешение запороли
                  Ответить
                  • > по последнему биту
                    А такое решение довольно часто юзают для интерпретаторов.
                    Ответить
                    • и что, не жалко целого бита?!
                      Ответить
                      • Ну иначе ты ещё одно слово потратишь или вообще мелкие числа в куче будешь аллоцировать.

                        В какой-то реализации лишпа вроде 2 бита откусывали.
                        Ответить
                        • меня больше расстраивает что sizeof поломатый
                          Ответить
                          • Во всяких питонах на sizeof в большинстве случаев похуй.
                            Ответить
                            • ну сипайтон же сишная программа же?
                              как же можно сломать sizeof?
                              Ответить
                              • Так ты про сишный sizeof штоле? А его можно поломать?
                                Ответить
                                • union {
                                      long i;
                                      struct {
                                          unsigned long length;
                                          digit digits[1];
                                      } bignum;
                                  };


                                  что вернет sizeof для этого униона?
                                  Ответить
                                  • Там точно такую поебень предлагали?!
                                    Ответить
                                    • https://www.python.org/dev/peps/pep-0237/#implementation
                                      да, но ее зарубили


                                      а теперь представь что будет если такой union вернуть или передать в качестве оргумента
                                      Ответить
                                  • Не вижу здесь поломки sizeof.
                                    Ответить
                                    • путих, смотри:

                                      этот юнион может или представлять обычный Long или bignum.

                                      тогда в length Хранится длина (в байтах)
                                      а в digits хранятся данные
                                      там может быть массив из 44х цифр

                                      sizeof будет думаь что там одна цифра, Но по факту их 44
                                      это можно только понять в коде пр length.

                                      это слдомает sizeof

                                      и такой union кроме как через указатель никак ине передать
                                      Ответить
                                      • Да похуй на сайзоф. Можно функцию написать. Но эта хуйня только через указатель передаётся. Непонятно тогда зачем оптимизация. Куче похуй 4 или 8 байт хранить, всё равно блок 2 слова.
                                        Ответить
                                        • оптимизация вероятно в том чтобы работать с long напрямую, потому я не ебу что лежит в массие байт

                                          может быть там число 222 представлено как 3 байта (digitа)

                                          децилмал бинари энкодингш
                                          Ответить
                                          • Да ьам скорее всего те же лонги и лежат для пирфоманса.
                                            Ответить
                                            • лал
                                              то-есть digit вовсе не digit?
                                              Ответить
                                              • Если там байты - то они вообще пизданулись.
                                                Ответить
                                                • К сожалению мы этого не узнаем. Чувак был послан нахуй в далеком 2001м году (когда вообще не знал о существовании питона!). Можно читнуть рассылку за тот год, но мне лениво

                                                  зы: а не, вру, Знал. Слака ставила питона и так я о нем узнал, но я на нем не писал конечно
                                                  Ответить
                                            • давай попездим про то что будет если такуюхуйню передать в функцию как аргумент

                                              если там колконвешнен такой что вызываетль создает в стеке структуру и передает ее указатель через EAX то все будет работать же внезапно? или ее попытаются скопировать в стек?
                                              Ответить
                                      • sizeof нормально работает, просто в сьруктурк вчех этих цифор нету, ведь sizeof всегда возращает только размер самой струкцуры. Будь она не в унионе была бы та же хуйря.
                                        Ответить
                                        • ну так sizeof вернет неверный размер этой "структуры"!
                                          он же не умеет читать length

                                          короче, чувак сломал к ухям частьс исечки
                                          * передачу по значению
                                          * sizeof
                                          * массив из такой хуни тоже не сделать

                                          байтоеб дегрейднул сисечеку почти до асемблера
                                          Ответить
                                          • Да похуй, если честно, главное чтобы профит какой-то был.
                                            Ответить
                                          • > вернет неверный размер этой "структуры"
                                            Открою секрет, струкьуры в сишке фиксированного размера, никакой sizeof нигде тебе не будет читать поля структуры.

                                            > передачу по значению
                                            Жто же питно, в нём всё в куче, функции принимают только оказатели.

                                            > массив из такой хуни тоже не сделать
                                            указатели.
                                            Ответить
                                            • Спасибо копетан.
                                              Еще раз попытаюсь донести свою мысль:

                                              В сишке обычно структуры или юнионы имеют предсказуемый (получаемый через sizeof) размер

                                              Приведенный мною пример это ХАК. По причине этого ХАКА с этой "структурой" (не сишкин термин а впринципе это структура данных -- кусок памяти) работать через sizeof нельзя
                                              Ответить
                                              • > ХАК
                                                Если хак приносит профит - вай нот?
                                                Ответить
                                                • >Если хак приносит профит - вай нот?
                                                  да ради яхве!

                                                  но я говорю что таким образом мы лишаем себя права использовать sizeof
                                                  Ответить
                                                  • Ну лишаем и лишаем. Хуй с ним. Мне насрать. Идиома (можешь называть её хаком) с массивом размера 0 или 1 в конце струк уры довольно часто юзается в сишке.
                                                    Ответить
                                                • Этот хак стоит в исключениях стандарта потому, что массово используется?
                                                  Или он проходит по стандарту и так?

                                                  Что я вижу:
                                                  * Выход за границу массива
                                                  * Игнорирование перестановки полей структуры компилятором
                                                  * Игнорирование паддингов, в которые нельзя писать
                                                  Хотя, я всех тонкостей, разумеется, не знаю. Но, если учесть капризность стандарта и безумные правила для UB, любой другой код в аналогичной ситуации наткнулся бы на одну из этих проблем и улетел бы в UB.
                                                  Ответить
                                                  • Х.з., походу массив в конце структуры - очередной специальный случай. Я не уверен, что это сработает для массива в середине.

                                                    А переставлять поля и так нельзя.
                                                    Ответить
                                              • Джигиты это просто демонический массив, сама структура —– просто заголовок, с ней сайзов работает как положено. Никакой sizeof размер демонического моммива не вернёт. Тут всё норсально.

                                                А теперь приведи мне свою реализацию где sizeof бы работал как ты кочешь.
                                                Ответить
                                                • dgigit[1] это статический массив

                                                  то что его юзают как динамический это ХАК
                                                  Ответить
                                                  • dgigit[1] это просто хуйня для того чтобы можно было читать данные, а заодно и дополнительная память в юнионе, чтобы было где битик возводить. И в сишке это норма. Не зря же flexible arrays придумали.
                                                    Ответить
                                                    • это не флексибл эррй же (их не было с C89), это хак)
                                                      блин!

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


                                                  да я не спорю что по другому никак

                                                  я всего лишь сказал что это ХАК

                                                  потому что чуваки хотят динамический массив не через указатель
                                                  Ответить
                                              • Ну и с такими структурами обычно делают функцию в духе allocate_number() и не парятся с sizeof().
                                                Ответить
                                              • > В сишке обычно структуры или юнионы имеют предсказуемый (получаемый через sizeof) размер
                                                С чего ты это взял?
                                                struct Peetooh {
                                                    char *name;
                                                    unsigned char color[3];
                                                };
                                                Ответить
                                                • Ну структура, в ней указатель и три чара. Шо тут не фуксировано?
                                                  Ответить
                                                  • Вот именно, что ничего — как и в примере восьмого гостя выше. А вот суммарный объём памяти, который будут занимать подобные структуры, вполне себе нефиксированный, что, по всей видимости, гостя и не устраивает.
                                                    Ответить
                                                    • я говорю что эта структура с точки зрения языка си занимает long + digit[1]

                                                      то что ее используют по другому это ХАК


                                                      то как рефлексия в Java или dynamic в C#. Это не стандартное использование языка
                                                      Ответить
                                                • размер указателя на char + 3 чара -- вот размер твоей структуры

                                                  что не так?
                                                  Ответить
                                                  • >>> что вернет sizeof для этого униона?
                                                    >>>
                                                    union {
                                                        long i;
                                                        struct {
                                                            unsigned long length;
                                                            digit digits[1];
                                                        } bignum;
                                                    };

                                                    Размер long + sizeof(digit), что не так?
                                                    Ответить
                                                    • все так

                                                      но с помощью этой структуры описывают структуру БОЛЬШЕГО размера

                                                      то-есть sizeof с ней использовать нельзя

                                                      я это и называл словом ХАК
                                                      Ответить
                                                • Я бы лучше этот пример привёл:
                                                  struct petux {
                                                      size_t size;
                                                      char data[];
                                                  };
                                                  У такой хуйни размер брать нельзя.
                                                  Ответить
                                                  • это вообще не могло работать с C99 кмк
                                                    Ответить
                                                    • Наоборот, это добавили в "C99".
                                                      Ответить
                                                      • да, этого не было с 89
                                                        именно потому (в 2001 году) они сделали не флекс аррей (gcc мог ине уметь тогда C99)
                                                        Ответить
                                                      • вот представь что ты сделал тип petuh с таким union

                                                        потом ты пишшеь

                                                        petuh p[42]

                                                        что будет?
                                                        бдует говно!! а значит еще и массивы изнего делать нельзя
                                                        Ответить
                                                        • Так не делай это говно! Нада в петуха совать укайзатель, томушо этот union только начало блока памяти произвольного размера.
                                                          Ответить
                                                          • ну то-есть ты согласен что испольщование этого приема лишат меня возможностей юзать массив?
                                                            Ответить
                                                            • Ты ещё пожалуйся что нельзя сделать массив демонических массивов, а только массив укахателей.
                                                              Ответить
                                                    • -99
                                                      +89
                                                      Ответить
                                                      • А до C99 юзали массив из одного элемента.
                                                        Ответить
                                                        • причем это решение не равно указателю!

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

                                                          а в случае массива из одного элемента они лежат дальше за структурой.

                                                          Короче может быть для бородатых сишников (типа Борманда) это и "идиома", но для меня это точно хак
                                                          Ответить
                                                          • Такая структура обычно лежит перед мосивом:
                                                            struct petux *petya = (struct petux*)malloc(filesize);
                                                            fread(petya, filesize,1, filepetya);
                                                            Поля Пети заполнились нужными данными, за ним лежит массив, теперь мы можем с ним работать. petya->data[petya->size - 1] последний элемень масива. Всё хорошо и красиво.
                                                            Ответить
                                                          • > бородатых сишников
                                                            Бородатым сишникам не нравится выделять по 2 куска памяти на каждый чих, поэтому и юзают такую хуйню для всяких строк, блобов да длинных чисел.

                                                            Вся суть в аллокации хедера и данных одним блоком. А идиома с массивом - просто для удобства, чтобы меньше кастовать. Можешь выкинуть массив и переименовать структуру в number_header.

                                                            З.Ы. Даже в крестах make_shared() делает нечто подобное чтобы склеить счётчики и объект в одну аллокацию.
                                                            Ответить
                                                            • Там не только с аллокацией проще, но ещё и копирование, чтение из файла, запись в файл, memcmp и с прочей хуйнёй с одним куском памяти проще работать.
                                                              Ответить
                  • А я говорил про другую оптимизацию, когда объекты (указатели на них) и мелкие числа совмещены в один тип размером в uintptr_t и разруливаются по биту.
                    Ответить
    • > UB
      Да похуй на UB, оно вообще не работает (отрицательное d засрёт своим знаковым битом всё остальное). Или у автора там беззнаковый чар?
      Ответить
      • То есть ещё во время каста будет так называемое расширение знака?

        Кстати, у некоторых кококомпиляторов есть переключатель «signed char/unsigned char».
        Ответить
        • А я думал, что chad всегда singed.
          Ответить
          • Он же вроде хрен знает какigned, если не специфицировать signed/unsigned.
            Ответить
        • > переключатель «signed char/unsigned char»
          Т.е. это на случай, когда пишут не signed char, не unsigned char, а просто char?
          Ответить
          • ЕМНИП это ID.

            char разработан лишь на столько, чтобы вместить в себя 127 банок сгущенки
            вместит-ли он 128ю зависит от покулятора


            я рекомендую всегда явно писать сигнет или унсигнед
            а еще лучше писать uint8_t
            Ответить
            • А про что тогда безумный петух говорит?
              Ответить
              • А кто его разберёт. Он же безумный.
                Ответить
              • Я про тот случай, когда нет явного спецификатора signed или unsigned. В одних компиляторах по умолчанию signed, в других unsigned, а в некоторых есть ключ командной строки или опции конфига, которыми можно выбрать знаковость/беззнаковость чара, если программист явно знаковость не указал.
                Ответить
                • бля, это и называется Implementation Defined, чи нi?
                  Ответить

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