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

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
// почему это гавно не будет работать?
auto size = buffer.size() - 1;
auto *ptr = new byte[size];
for (auto i = size; i >= 0; i--)
{
    ptr[i] = 0;
}

// a это гавно будет работать :)
auto size = buffer.size() - 1;
auto *ptr = new byte[size];
for (int i = size; i >= 0; i--)
{
    ptr[i] = 0;
}

почему это говно не будет работать?

Запостил: ASD_77 ASD_77, (Updated )

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

  • Ответ: по мнению стандарта и тот и другой варианты — UB. ptr[size] за пределами массива.

    А так да, камешек в огород любителей беззнаковых значений.
    Весело будет, если size() вернёт когда-нибудь 0
    Ответить
    • >ptr[size]
      вроде, туда ходить можно, а разыменовывать нельзя, не?
      или это тока для указателей

      впрочем, лунь туда один хуй пишет
      Ответить
      • ptr + size можно написать, это ещё валидный указатель. Но разыменовывать его нельзя. А скобки вроде как уже подразумевают разыменование, даже если ты получившееся lvalue потом не юзаешь. Читать и писать тем более нельзя.
        Ответить
  • > auto size = buffer.size() - 1;
    < size = -1
    > new byte[ -1];
    < говно
    Ответить
    • Там не -1 если чо, размеры в крестах беззнаковые. Но аллокатор всё равно bad_alloc кинет, да.
      Ответить
        • Ну да, когда ты совершаешь операцию над знаковым и беззнаковым интом, то знаковый кастуется к беззнаковому (охуенно интуитивно, ага).
          Ответить
          • и так трудно, а еще auto эти дурацкие пишете.. если бы там был size_t, то я бы допёр

            вообще, ауты нужны, чтобы параметризованные итераторы не выписывать. А для простых типов я бы его не
            Ответить
            • Именно поэтому я против auto в тех местах, где конкретный тип не на километр.
              Ответить
              • И в шаблонах можно, где ты шо так шо эдак конкретного типа не знаешь.

                template<typename T> example(T t) { T::value_type x = t[i]; } → example(T t) { auto x = t[i]; }
                Ответить
                  • Там ещё возвращаемый тип, объявление i и полезные действия с x отклеились :). А так да, зависимому типу нужно указывать, что он тип.
                    Ответить
                    • Да я просто на днях портировал код с msvc на шланг, теперь вот отходняки, зависимые типы без typename глаза режут.
                      Ответить
                • сложная хуйня какая-то .. пиши так

                  auto example(auto t) { decltype(t[i]) x = t[i]; }
                  Ответить
            • Подтверждаю. Меня как-то вербально отпиздили за то что мои var (речь про другой язык) на ревью нихуя не понять что за собой скрывают. Тогда-то я и Понял.
              Ответить
    • а вот и нет. т.к. размеры это беззнаковый типа то auto size = (size_t) 0 - 1 = 0xfffffffff а это есть положительное число
      Ответить
      • а стандарт гарантирует, что переполнение нормально отработает, или будет UB?

        unsigned int i = 0;
        i--;
        равен ли он теперь MAX_INT?
        Ответить
      • g: size_t max value

        So the minimum maximum value that size_t must be able to hold is 65535, which is 16 bits of precision, and size_t is only defined to be an unknown unsigned integer type.

        Какой анскилл )))
        Ответить
  • Оптимизировал:
    auto *ptr = calloc(size, 1);

    З.Ы. Вроде ещё что-то типа такого можно, но я не уверен:
    auto *ptr = new byte[size]();
    Ответить
    • А нельзя разве как со обычным моссивом new byte[size]{0}?
      Ответить
        • З.Ы. Бля, когда я последний раз массив в куче инициализировал? В лабе разве что. И то не факт.
          Ответить
          • Когда ты последний раз вообще new писал? небось до ++14, когда make_uniq завезли всякие?
            Ответить
            • Собеседующий: что делает оператор delete
              Борманд: да хуй знает, не юзал ни разу
              Ответить
              • --у вас в С++ ручное управление памятью
                --А разве не RC, как в ObjC?
                Ответить
                • -- у вас в С++ ручное управление памятью
                  -- нет, это у вас в джаве ручное управление ресурсами
                  Ответить
                  • -- у вас в С++ ручное управление памятью
                    -- У вас вообще его нет

                    самое печальное с жабой и другими мейнстримовыми языками без управления памятью - что сервисы для перемалывания больших данных, запросов, etc. пишут именно на них, а вот ограничить сверху расход памяти конкретным запросом/джобой невозможно, и потому какие circuit breaker'ы не ставь, всё равно рано или поздно не успеешь отловить OOM,
                    Ответить
                    • в C# можно хотя бы изъебнуца со стеком через value types, а в джавке есть этот.. Шипилёша сделал.. GC, который ничего ничего не чистит. Сразу выделяет память, и как только ты ее заполнил -- получи OOM
                      Ответить
                      • В джаве тоже можно как-то память вручную аллоцировать, но это всё равно мертвому припарки, придется писать свой надязык чтобы в этом размещать свои типы. А вообще стека не хватит на то, про что я говорю, речь о всяких штуках, которые могут попробовать гигабайт себе захватить.

                        Именно поэтому у меня есть очередная NIH-мечта - выкинуть нахуй Lucene и написать всё по-человечески на сишке.
                        Ответить
                        • > выкинуть нахуй Lucene и написать всё по-человечески на сишке

                          Хм, а CLucene это не то?
                          Ответить
                      • А, хотя один пуленепробиваемый вариант есть. Форкать процесс, возвращать оттуда результат, и позволить при необходимости ООМнуться. Только хахахаха он же перед ООМ пойдет делать GC да кучу дефрагментировать, т.е. вся эта ваша CoW память сразу в пизду, а это значит каждый форк будет жрать столько же, сколько родительский процесс, а так как динамически максимальный размер хипа толком не потюнить, то придется все процессы сразу создавать с таким хипом, чтобы в него эти гигабайты могли поместиться, а это в лучшем случае свап, в худшем счет от амазона за терабайт оперативы.

                        Тут конечно можно сказать: зачем форкаться, если можно создать новый процесс? А новый процесс это инициализировать новую вм ахаххаха опять весь пирформанс в пизду.
                        Ответить
                        • форкать джаву?чтобы она там прогревалась и джитилась каждый раз?
                          Ответить
                            • пиздец сколько ебанины вместо того, чтобы взять яп с RC
                              Ответить
                            • блядь, у меня и так счета за отопление пиздец, а ты тут это
                              Ответить
                          • Форк-то как раз прогревать не надо, в этом плане с ним всё в порядке. Вот то что память нихуя не переиспользуется, как при форке приложения на нормальном языке - это да.
                            Ответить
                            • > память нихуя не переиспользуется

                              Ну если хорошенько прогреть, чтобы всё проджитилось, gc несколько раз отработал и убрал всю статику в олдфажное поколение, вроде должно норм получиться.

                              Форк насрёт в быстрое поколение и сдохнет, а жирный общий контекст останется расшаренным.
                              Ответить
                              • Мы говорим про приложения, которые перемалывают гигабайты. Фулл ГЦ придет очень быстро и пересоберет всю кучу.
                                Ответить
                            • расскажи про форк. Почему не нужно прогревать? Потому что корова уже прогрета, и она шарица?
                              Ответить
                              • Потому что прогрев - это компиляция методов согласно собранным профилям, и да, дочерние процессы получат уже прокомпилированные компилятором второго уровня методы.
                                Ответить
                                • я пнял, да. Если ты не сделаешь exec поверх форка, то секция кода у тебя та же будет

                                  Кстати, как ты это сделаешь в винде?
                                  Ответить
                                  • винда не нужна

                                    хз, я просто не знаю достаточно про винду, только про то что ты имеешь в виду что там вместо fork-exec StartProcess, который ничего не шарит
                                    Ответить
                                    • CreateProcess там, угу.

                                      В никсах ты делаешь fork, получая копию себя (благодаря корове очень дешевую), а потом ты делаешь exec поверх если хочешь.

                                      В пинде ты явно запускаешь новый процесс.
                                      Конечно, если ты перезапускаешь то, что уже есть в памяти, то винда может постараться переиспользовать странички c кодом, но я не ебу что там с джитом будет.

                                      А вместо fork там потоки.

                                      зы: Борманд наверняка знает
                                      Ответить
                                      • > но я не ебу что там с джитом будет

                                        Заново джитить всё будет.

                                        Цыгвин как-то пытается "форкнуть" процесс на венде (через явное шаред мемори?) но там куча проблем с этим, это вообще не продакшен-реди.
                                        Ответить
                                        • Мне птичка напела, что само ядро имеет сискол fork (для почившей в бозе юниксовой подсистемы) но в Win32API он не распаян
                                          Ответить
                          • Фу, у тебя пхп в профиле


                            нафоркай себе сколько-то долгоживущих процессов, создай direct buferы в обычной памяти заранее заданного размера, и не вылазть за них

                            placement new в жову не завезли, так что придется тебе вместо объектов массивами оперировать, как Царь

                            и не будет никакова GC
                            Ответить
                            • в том-то и проблема что там блядский люсин, который сам творит в джаве че хочет и который так или иначе надо к хуям переписать
                              Ответить
                              • а есть же sphinx или какой-то такой, на цисгендерном языке написанный, без гэцэ

                                не пробовал его?
                                Ответить
                                • Боротьба с GC напоминает мне войну с отсутствием стат типизации в мире питоноблядей или борьбу с отсутствием классов в старом JS или перле.

                                  Зачем бороться с тем, что тебе не подходит?
                                  Выкини, да возьми другое.

                                  Управляемая куча говна не лучший инструмент для высокоперформансного хайлоада бигдаты
                                  Ответить
                                  • > Выкини, да возьми другое.

                                    Именно поэтому я за кресты. Там говно на любой вкус есть. Даже gc и jit при желании.

                                    Комплайт-тайм рефлексию и кодогенерецию вот дождаться осталось...
                                    Ответить
                                  • > Выкини, да возьми другое.

                                    Именно поэтому я за кресты. Там говно на любой вкус есть. Даже gc и jit при желании.

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

                                    тут мы возвращаемся к исходному сообщению

                                    > самое печальное с жабой и другими мейнстримовыми языками без управления памятью - что сервисы для перемалывания больших данных, запросов, etc. пишут именно на них

                                    нету другого эластика и другого люсина
                                    Ответить
                                      • он и в подметки не годится

                                        > Partitioning is done manually.

                                        дальше уже и читать смысла особо нет
                                        Ответить
                                    • > нету другого эластика и другого люсина

                                      CLucene протух, получается? Какая-то уж больно древняя версия у него по сравнению с настоящим.
                                      Ответить
                                      • Я даже не слышал про него, что видимо означает да. Люцен очень активно всякую хуйню добавляет, хотя вместо этого лучше бы позаботился о глазных кровотечениях при попытках разобраться в коде.
                                        Ответить
                      • > Сразу выделяет память, и как только ты ее заполнил -- получи OOM

                        Т.е. "PHP" всё-таки не говно, раз его основной принцип перенесли в жабу?
                        Ответить
  • кароче прикол в том что если сделать size = uint_t то цикл никогда не закончиться потому что i никогда не будет ниже нуля 🙂
    Ответить
    • Надо предупреждения включать:

      warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits]
      Ответить
      • Не поможет.

        for (size_t i = 0; i < pidor_v.size()-1; ++i) { // итерируемся до предпоследнего
        Ответить
        • Ну я же про конкретную ошибку, когда пытаешься устремить i к нулю, а оно беззнаковое. Понятно, что все ситуации не отловить, это же не coq.
          Ответить
        • какой багор:) Это нужно явно проверять каждый раз, что вектор не пустой?
          Ответить
          • В общем-то нет, если ты хочешь просто все элементы обработать. А здесь же "все кроме последнего", т.е. должен быть как минимум последний, т.е. надо убедиться что не пуст.

            Хотя со знаковым числом этой фигни бы не было, конечно.
            Ответить
            • Ну я про это и говорю, бо если я из ноля вычту 1, то получу оче большое значение же, и уйду за пределы массива

              со знаковым я бы получил -1, а 0 не меньше -1, и все кончилось бы хорошо, не?
              Ответить
        • Из серии «хотелось бы как-то возразить, да нечем»

          Кампутир сайенс положил семантику на лопатки
          Ответить
        • Пофиксил:

          for (size_t i = 2; i < pidor_v.size(); ++i) {
          . . . . auto j = i - 2;

          Ладно, побежал дальше писать работающие программы на unsigned вычислениях, а вы продолжайте хуесосить ЛУЧШЕЕ, что когда либо было создано в программировании 😉
          Ответить
    • москали соснули, говно из сливных отверстий сухарных мишочков будет заливать квадратную барсетку
      Ответить
  • Теперь будет работать как надо:

    #define UNSIGNED_NIL UINT_MAX
    
    /* тут еще всякий код */
    
    for (auto i = size; i != UNSIGNED_NIL; i--)
    {
        ptr[i] = 0;
    }
    Ответить
  • Беззнаковый размер в крестах - это ублюдская историческая ошибка, которую признали и дохлый страус, и любитель тухлой рыбы.
    Ответить
    • но ведь по типу все верно . кол-во не может быть меньше нуля.
      Ответить
      • зато нельзя сделать так
        if (size - 1 > 0)..

        нужно было делать как с указателями: чтоб вылазить за пределы ( в отрицательные значения ) было можно, а обращаться по ним нельзя
        Ответить
          • так это абсолютно валидный код. Выж сами говорили, что для беззнаковых типов переполнение это ок.

            Вдруг мои вкусы специфичны, и я именно это и хотел написать?
            Ответить
        • Кстати на тебе ещё прикол:
          int size = 3;
          
          if (size - sizeof(uint32_t) > 0)
          Т.е. если менять тип, то вообще везде. Один unsigned может всё выражение зашкварить.
          Ответить
          • size перватится в unsigned int, и будет true?

            а если бы я сказал size = -1, то что бы случилось? unsigned превратился бы в signed?
            Ответить
            • > unsigned превратился бы в signed

              Наоборот же. Будет 0xFFFFFFFFu - 4u > 0u.
              Ответить
              • я просто не помню, какие типы во что расширяются.
                помню тока, что операторы любят, чтобы операнды были одинакового типа)

                вообще имплиситный каст есть говно, и лучше бы его не было
                Ответить
                • Блядь, да там пиздец...

                  Сначала мелочь меньше инта кастится в int. Затем, если получились типы разного размера, то кастится в больший из них. А если одного -- то в беззнаковый.
                  Ответить
                  • нужно смешать это с перегрузкой, и задавать задачки на собеседовании типа "какая из восьми перегрузок метода вызовется в foo(bar - buz)"
                    Ответить
                    • void foo(int&& x);
                      void foo(unsigned&& x);
                      
                      uint8_t a, b;
                      foo(a + b);
                      Какой метод вызовется?
                      Ответить
                      • хм, зачем мувать инты?

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

                        блядь

                        там же создасца временная переменная и будет наоборот: вызовеца unsgined, а мог бы и вообще какой-нить float?
                        Ответить
                        • Ну да, создастся временный int, поэтому вызовется перегрузка с int&&.
                          Ответить
                          • вообще за такие перегрузки нужно с вертушки пробивать, я считаю.

                            Перегружать можно только то, что друг а друга не расширяется неявно
                            Ответить
            • А вот на более очевидное if (size > sizeof(uint32_t)) конпелятор таки ворнингует.
              Ответить
      • Потому что это приводит только к мучениям с singen unsingen mipmatch, а преимущество дает Толька в том, что максимальный размер стандартного контейнера ограничен 64k, а не 32k (про большие битности уже и не говорим) - довольно специфический сценарий, когда это важно.
        Ну и отсутствие явно неправильного значения -1, которое можно использовать как пустой результат (например, при поиске) - скорее, недостаток.
        Ответить
      • Потому что жил был на свете питух-жабоеб.


        И однажды он написал написал код
        int theBestIndexForKurochka = findTheBestPlace();
        if (theBestIndexForKurochka > -1) {
          kurochkas[theBestIndexForKurochka] = new Kurochka();
        }


        а потом код стал тормозить, и он решил переписать его кресты. Угдай, что случилось?
        Ответить
        • Наверное, компилятор выдал ворнинг. Жабоеб был умным, поэтому прочитал ворнинг и переписал программу аккуратно, добавив нужных кастов и проверок. Но потом долго плевался: да что за язык такой, что на ровном месте грабли.

          С другой стороны, а вдруг нам действительно нужен массив ровно в 64к. Язык должен это поддерживать, чай не скриптушня. Для каких-нибудь std::vector можно было и ограничить размер: хотите странных размеров, создавайте массив ручками, обойдетесь без классов. В Qt, например, так и сделали, для прикладнухи этого достаточно. Но sizeof(char[64*1024]) же должен что-то возвращать. А, значит, конструкция типа int i = 16; if (i < sizeof(SKurochka) {...} уже будет потенциально опасной, даже если у меня в программе больших структур вообще нет, чего ругаесся, насяльника. В общем, сложно сказать.
          Ответить
          • > другой стороны, а вдруг нам действительно нужен массив ровно в 64к.

            Ну вот жабаеб может состнуть (и шарпей наверное тоже) даже на x64 системе.
            Однако будем честны: всем хватит 2^32 байт. Если не хватит, то нужно делать анонимный ммапинг файла, а не пхать массив.
            Ответить
            • > Однако будем честны: всем хватит 2^32 байт
              Нихватает. Всего 4 ГБ.

              > Если не хватит, то нужно делать анонимный ммапинг файла, а не пхать массив.
              Тут проблема не в массиве, а в адресации.

              Но я не припомню ос, которая разрешила бы замапить кусок памяти размером в 2^64.
              Ответить
      • тарас пояснил, почему
        for (size_t i = 0; i < pidor_v.size()-1; ++i) { // итерируемся до предпоследнего


        для пустого массива будет бугурт
        Ответить
        • Некрасивый пример. Для понятия "до предпоследнего" пустой массив - это особый случай и потенциальная ошибка. Тут лучше в любом случае добавить либо проверку, либо комментарий "нет, мы не забыли".
          Ответить
        • А если даже последнего нет, то как итерироваться до предпоследнего? Без ТЗ - результат хз.
          Ответить
  • Десять лет назад 500 мегабайт интернета стоили как сейчас безлимит.
    А всё потому что это был чистый концентрированный на сто процентов свободный интернет.
    Нынче такой интернет не делают, всё разбавлено цензурой, вот и продают за бесценок.
    Ответить
    • Это вроде шутка Чилика?

      В моем детстве Интернет по карточкам в метро продавался. Бывало купишь свежую карточку, и пока домой со школы бежишь -- всю и съешь...
      Ответить

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

Из-за тебя ушел bormand, guest!

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


    8