Кресты / Говнокод #25395 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  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 j123123, (Updated )

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

  • А где, собственно , 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-битном инте).
          Ответить
              • А что важно?

                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 внутрь...
                          Ответить
              • и в руби тоже
                тока он там переключица в Bignum или как оно тмм
                Ответить
              • в третьем пиздоне да
                а во втором Int и long были разными тупами с программным переключеним
                потом стал PEP237

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

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

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

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


                                что вернет sizeof для этого униона?
                                Ответить
                                  • путих, смотри:

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

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

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

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

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

                                        может быть там число 222 представлено как 3 байта (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), что не так?
                                                  Ответить
                                              • Я бы лучше этот пример привёл:
                                                struct petux {
                                                    size_t size;
                                                    char data[];
                                                };
                                                У такой хуйни размер брать нельзя.
                                                Ответить
                                                • это вообще не могло работать с C99 кмк
                                                  Ответить
                                                      • причем это решение не равно указателю!

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

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

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

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

                                                          З.Ы. Даже в крестах make_shared() делает нечто подобное чтобы склеить счётчики и объект в одну аллокацию.
                                                          Ответить
                                                          • Там не только с аллокацией проще, но ещё и копирование, чтение из файла, запись в файл, memcmp и с прочей хуйнёй с одним куском памяти проще работать.
                                                            Ответить
                                                    • да, этого не было с 89
                                                      именно потому (в 2001 году) они сделали не флекс аррей (gcc мог ине уметь тогда C99)
                                                      Ответить
                                                    • вот представь что ты сделал тип petuh с таким union

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

                                                      petuh p[42]

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

      Кстати, у некоторых кококомпиляторов есть переключатель «signed char/unsigned char».
      Ответить
        • Он же вроде хрен знает как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?
                Ответить

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

Помни, guest, за тобой могут следить!

    А не использовать ли нам bbcode?


    8