Забавные новости 0й-Ti :)

Тема в разделе "WASM.HEAP", создана пользователем UbIvItS, 18 июн 2018.

Статус темы:
Закрыта.
  1. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.460
    Адрес:
    Россия, Нижний Новгород
    Не, я имею в виду, что какой смысл сравнивать реализации на интринсиках, если фактически ты будешь сравнивать ручную ассемблерную реализацию с такой же ручной ассемблерной, просто завёрнутую в другой язык. Нас ведь интересует, насколько хорошо компилятор оптимизирует обычный код.
     
  2. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.241
    компиль-тайм ошибки гораздо менее опасны, чем рантаймовые и в этом плане сишный компиль не многим тупей адового.
    скриптовый двиг читает скрипт и исполняет соответствующие асм команды. короче, аким дикобразом одно переводится в другое тут не важно - в любом случае переводится :)
    на одном проце эта команда есть, а на другом её нет и там заместо интринзика компиль молотит подстановки + компиль может чекать входные данные и/ль подлепить рантайм чекер + в бинаре может стоять переключатель, кой решает когда подключать интринзик, а когда его замену. ну-и, последнее == да, асм вставки могут юзаться для сокрытия неэффективности компиля.. Тут уж о глубинных причинах такого подхода нужно вопрошать у тех прогеров. если б секта ржавого играла бы честно, то ансейфы были бы для них табу :)
     
  3. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.460
    Адрес:
    Россия, Нижний Новгород
    Неа, интринсики вставляются в код как есть, компилятор не имеет права их заменять. Он вставляет только сопутствующий код для передачи параметров в инструкцию интринсика.
    То есть, на интринсиках ты пишешь чуть-чуть выше, чем на сыром ассемблере.
    Единственное, что компилятор откажется собирать - если ты вставляешь интринсик из другого набора инструкций (например, собираешь под ARM, а пытаешься вставить интринсик от x86).
    Если же собираешь под конкретный процессор, а он не поддерживает интринсик - то варианта два: или соберёт именно с ним, или не соберёт. Но никогда не заменит его на аналог.
    Во всех остальных случаях в бинарнике ты увидишь именно ту инструкцию, которую написал.
    Так в сишных бенчмарках тоже юзают интринсики. И получается, что ты одну и ту же ручную ассемблерную реализацию сравниваешь с самой собой (иногда даже один к одному), просто вызванной в другом языке. Ну такое ~

    А ансейф - это такой же равноправный элемент языка. Всегда будут случаи, когда что-то невозможно выразить в безопасной парадигме.
    Например, доступ к KUSER_SHARED_DATA. В винде он всегда лежит по фиксированному адресу, но т.к. сам факт наличия такого адреса ниоткуда не следует (ты его не выделял, он просто взялся изниокуда) - раст никак не может убедиться, что доступ к нему безопасен.
    Поэтому ты просто говоришь ему: "Беру ответственность на себя, разыменовывай" - и нет проблем.

    И в ансейфе, на самом деле, разрешено далеко не всё. Например, правила заимствований продолжают работать и для сырых указателей, поэтому устроить гонку в ансейфе можно только намеренно, если задаться целью.
     
  4. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.330
    Гораздо тупее, объявил ты range тип от 0 до 100, а потом к нему попробовал прибавить 101 в процедуре, это переполнение будет отловлено в компайл тайме. В Цэ ты никакой абстракции над целыми числами объявлять не можешь, есть 32-бита под целое и живи с этим как хочешь. Или объявил ты два типа: Цельсий и Фаренгейт, и переменной с Цельсием не можешь присвоить Фаренгейты, не вызвав функцию конвертации одного в другое. А в Цэ и то и другое - обычные 32-битные целые, которые всегда можно перепутать, если ты не элитный цэшный дед, который никогда в своей жизни ни одного указателя не прое... ну ты понял.
    --- Сообщение объединено, 21 ноя 2023 ---
    Я помню, оголтелые адепты захейтили бедного автора на секундочку самого быстрого веб-сервера на ржавом до того, что он самовыпилился из оупенсорса. Многие там считают, что ансейф для рукоблудов, а правые во всем ржавые поцоны только в сейф кодах живут.
     
  5. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.460
    Адрес:
    Россия, Нижний Новгород
    Ага, такое было - это про ActixWeb. Вообще, я в детали не вдавался - возможно, хейт был и по делу: например, его ближайшие конкуренты - Rocket и Hyper - показывают плюс-минус такую же скорость, а написаны без ансейфа (вроде).
    Тут и сообщество можно понять: веб-сервера - это буквально то, где ансейфа хочется по минимуму)
    Но тут каждому своё - я не считаю его чем-то страшным (да и нужен он довольно редко).
    --- Сообщение объединено, 21 ноя 2023 ---
    [​IMG]
     
  6. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.241
    сишка - это логическое продолжение асма, она делает минимально возможный оверхед и, зачастую, ручной асм код сишку обогнать не может и дело даже не в умности компиля, а в том, что за десятки лет в компиль напихали наиболее скоростные костыли, кои и пихаются в бинарь .. однако, иногда асм вставки нужны. у ржавого же фетиш сейфовых функций и тут возникает простой Вопрос: аким дикобразом этого можно достичь???

    * железки с дыреньками, а самые топовые игровые жестянки тупо пашут в аварийном режиме - если раньше разгоняли железки дурачки энтузиасты, то сейчас их такими продают.
    * на кой 4ёрт вообще писать на ржавом, если все оси и вся их оснастка на сишке??? невозможно использовать никакое апи без ансейф вызовов.
    вот и получаем очередную кашу из топора :)
    если используется адреса из ниоткуда - это уЖО и есть потенциальные забеги. вот и получаем вилку..
    * задаём больше ограничений - РАСТёт несовместимость со средой исполнения.
    * пишем ансейфом а-ля сишка, так смысл сейфа РАСТёт в зеро.

    ЗЫ.. мы можем вспомнить чем окончилась борьба с дыреньками процев - все просто офят ту защиту ко всем 4ертям :)
    ёклмн, акие абстракции в реалтайме.. иль это так необходимо переводить цельсий в фаренгейты в ядре оси??? :) а если Тебе так приспичило - задай функи (одна считает ц, другая ф)...

    int F_degs(int val, int code_4_op){
    int static deg = 0;
    if code_4_op == __GET__ {
    return deg;
    }
    if code_4_op == __ADD__ {
    return val + deg;
    }
    //.................
    }
     
  7. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.460
    Адрес:
    Россия, Нижний Новгород
    А я и не спорю. Но баланс возникает сам собой: тебе ансейф зачастую просто не нужен.
    Необходимость в нём возникает, когда надо или работать с сырой памятью и указателями, или с внешними либами/API на других языках. Или непосредственно с железом.
    И всё это требуется нечасто. А где требуется, ты заворачиваешь всё в безопасные обёртки, и дальше работаешь с ними.
    То есть, какой-то ансейф остаётся, но он локализован в отдельных модулях, и ты уже знаешь, что вон там условный format C: произойти может, а вон там, где не ансейф, не может.
    Ну, во-первых, он прикольный. А во-вторых, мы считаем окружение условно безопасным: если там есть баги - мы с ними ничего не сделаем. Но зато в нашем собственном коде от наших собственных багов немножко убережёмся.
    А её в расте просто не отключишь. Там нет годмода, который разрешит делать всё. Ты хоть обложись ансейфом, но пока не удовлетворишь компилятор - бинарник не соберёшь.
    И на самом деле, порог вхождения в раст НАМНОГО выше, чем даже в плюсы с их шаблонами. У тебя просто не получится писать код так, как ты это делал в других языках.
    Это сродни поговорке про мышей и кактус - писать на расте сложно, ты буквально страдаешь, но что я заметил по себе - код практически не надо отлаживать. Как только rust-analyzer в вскоде перестал ругаться, ты можешь быть уверенным, что сейчас ты запустишь проект, и он будет работать именно так, как тебе надо, с первого раза.
    В плюсах это постоянный цирк: написал простыню, запустил сборку - на подстановке какого-то шаблона не собралось. Переписываешь, собираешь - не собралось (а редактор тебе фиг подскажет, потому что он сам не знает, валидный у тебя код или нет). Переписываешь, собираешь, успешно: запустил - упало.
     
  8. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.241
    а что значит "не нужен"? куча прог больше, чем на половину, состоит из вызовов апи. более того, практически любой яп подходит для лабания обёрток и раст в этом плане ничего интересного не добавляет. опять же повторюсь (мы с тобой уже на эту тему говорили) - основная защита всегда строится на физическом разделение потоков данных, поэтому заниматься графоманством особо "секурного" кода попросту излишне.. это, к примеру, во времена той же энтишки 4.0 железки были дорогие и в один сервач пихали всё, что ни попадя. а ща ханипот на ханипоте и каждый целевой сервак получает узкую функцию :)
    ох, уж эти растолюбы - отлаживать не надо, но они страдают :crazy::crazy::crazy: проблемность отладки в сущности от яп-а не зависит == всё упирается в уровень задачи и текущих возможностей прогера. в расте просто процесс отладки во многом перепихнули в задачу компиляции. Однако, во множестве случаев от страданий в компиль-тайме толку-то мало. к примеру, очень любят рассказывать, молДе вот яп порождает сейф-тред код, где прям невозможны забеги потоков. просто берём любой комп и начинаем его гонять по стресс тестам и довольно легко найти режимы, где доморощенный thread-safe попрёт вкривь и вкось - в лучшем случае упадёт без доп сюрпризов, а в худшем и железки пожгёт :)
     
  9. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.460
    Адрес:
    Россия, Нижний Новгород
    UbIvItS, в целом, ты прав: безопасные обёртки можно писать на любых языках. Просто в расте возможностей обезопаситься больше.
    Например, хотим пройти по контейнеру и удалить какие-то элементы, которые удовлетворяют условию. Само условие для простоты опустим, пусть удаляет все подряд.
    Вот как это можно написать:
    Код (C++):
    1.  
    2. // Вариант 1:
    3. for (const auto& entry : container)
    4. {
    5.     container.erase(entry); // Boom!
    6. }
    7.  
    8. // Вариант 2:
    9. for (auto it = container.begin(); it != container.end(); ++it)
    10. {
    11.     container.erase(it); // Boom!
    12. }
    13.  
    14. // Вариант 3 (уже сложнее, выглядит безопасно, но всё равно невалидно):
    15. for (auto it = container.begin(); it != container.end();)
    16. {
    17.     auto current = it;
    18.     ++it;
    19.     container.erase(current);
    20. }
    21.  
    22. // Вариант 4 (правильный):
    23. for (auto it = container.begin(); it != container.end();)
    24. {
    25.     it = container.erase(it);
    26. }
    27.  
    (и в C++20 появился удобный erase_if, которому можно передать предикат).

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

    Например, вот есть код. Сможешь найти в нём проблему?
    Код (C++):
    1.  
    2. struct Klass
    3. {
    4.     void* buf;
    5.  
    6.     Klass()
    7.         : buf(malloc(...))
    8.     {
    9.     }
    10.  
    11.     ~Klass()
    12.     {
    13.         close();
    14.     }
    15.  
    16.     Klass& operator = (Klass&& klass) noexcept
    17.     {
    18.         close();
    19.         buf = std::exchange(klass.buf, nullptr);
    20.         return *this;
    21.     }
    22.  
    23.     void close()
    24.     {
    25.         if (buf)
    26.         {
    27.             free(std::exchange(buf, nullptr));
    28.         }
    29.     }
    30. };
    31.  
    32. Klass klass1;
    33. Klass klass2;
    34. klass2 = std::move(klass1);
    35.  
     
  10. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.241
    чой-то странное.. функа эрейс что именно возвращает???
    в данном случае бросается в глаза нульптр - зачем он там???
    --- Сообщение объединено, 21 ноя 2023 ---
    вот один из примечательных примеров багов в расте..
    в глобальном плане побороть такие ошибки невозможно - систему всегда можно поднагрузить и синхра пойдёт танцевать в пьяную :)
    --- Сообщение объединено, 21 ноя 2023 ---
    клоуз, конечно, тоже интересно сидит :)
     
  11. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.460
    Адрес:
    Россия, Нижний Новгород
    Итератор, который смотрит на следующий элемент после удалённого. Например: std::map<Key,T,Compare,Allocator>::erase - cppreference.com
    Обнуляем указатель в перемещаемом элементе, иначе в его деструкторе освободится перемещённый указатель, которым владеет уже другой владелец.
    Например:
    Код (C++):
    1.  
    2. Klass func()
    3. {
    4.     Klass klass1; // Выделил буфер и владеет им
    5.     Klass klass2; // Выделил буфер и владеет им
    6.     klass1 = std::move(klass2); // klass1 освобождает свой буфер, забирает буфер у klass2 и обнуляет его указатель на буфер
    7.     return klass1; // Здесь вызывается деструктор klass2.
    8.     // Если указатель в нём ненулевой, то его close() сделает указателю free(),
    9.     // освободив буфер, которым владеет уже klass1.
    10. }
    11.  
    Принимая владение чужими ресурсами, надо освободить свои.

    Пока проблему не нашёл - какие ещё предположения?

    Кстати, вопрос открытый: все, кто тут топит за безопасность средствами программиста, а не языка, дружно пробуем найти в этом коде баг.
    Представьте, что вы проводите code-review, встретили такой код. Что с ним не так?
     
  12. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.241
    как-то криптовано выглядит, можь лучше так..

    free(buf);
    buf = klass.buf
    --- Сообщение объединено, 21 ноя 2023 ---
    тоже плохая схема - итератор имеет смысл изменять явно.
    --- Сообщение объединено, 21 ноя 2023 ---
    чтобы что-то обнаруживать, давай сначала криптованность снимем :)
     
  13. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.460
    Адрес:
    Россия, Нижний Новгород
    Может и имеет смысл, но валидный код только тот, который в варианте 4.

    А напиши полную реализацию оператора перемещения, как ты его видишь
     
  14. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.241
    mov (*buf1, *buf2){
    free (buf1);
    buf1 = buf2;
    }
    --- Сообщение объединено, 21 ноя 2023 ---
    ret buf1; :)
     
  15. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    Очевидно, его писал рукожоп, ибо сырой указатель без счетчика ссылок никогда не выходит наружу из объекта владельца :) Это из-за таких багов у вас постоянно use-after-free в сишечке чтоле? :)
     
  16. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.460
    Адрес:
    Россия, Нижний Новгород
    А если на плюсах?
    А мы и пишем обёртку над сырыми указателями, чтобы завернуть его во что-то безопасное. Этим указателем может быть какой угодно ресурс (или группа ресурсов), требующий освобождения - указатель, хэндл или даже состояние.
    Да, довольно часто именно из-за подобных багов. Где-то что-то забыли проверить - и начинается цирк.
     
  17. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.241
    технически не везде должен быть счётчик ссылок = в основном достаточно проверить указатель (нуль али нет) :)
    зачем? логика понятна - дальше лень. я на плюсах в основном пользую оператор нью и классы юзаю редко - сишной стилистики вполне хватает. а слишком задвигать классами - ты свой же код потом перестанешь понимать, пч логика работы класса приводит к массе неявных преобразований :)
     
  18. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    Ну, тогда неудивительно, что у вас там все постоянно течет и переполняется :)
    Еще раз: сырые указатели никогда и не при каких условиях не покидают объект владелец. Если такой функционал необходим, указатель заворачивается в структуру со счетчиком ссылок и удаляет себя сам, когда больше никому не нужен.
     
  19. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.460
    Адрес:
    Россия, Нижний Новгород
    Так мы и пытаемся написать этого объекта-владельца. Например, нам CreateFile возвращает хэндл. Давай напишем RAII-обёртку для него, чтобы положить в неё хэндл и не беспокоиться, что он утечёт.
     
  20. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    Он должен быть всегда, если количество объектов, которые этот указатель могут пощупать больше 1.
     
Статус темы:
Закрыта.