Pull to refresh
4
0.1
Кривенков Роман @qwerty19106

Embedded

Send message

Классический код на Rust не "ориентирован" на объекты и их взаимодействие

Еще как ориентирован. В С++ наследование, а в Rust композиция. Это 2 разных подхода ООП, и у каждого есть свои плюсы и минусы.

С++ в совершенно обычном коде вызывает UB, чего не происходит в других языках. Посмотрите например последний пример по ссылке, связанный с Integer Promotion:
https://github.com/Nekrolm/ubbook/blob/master/numeric/overflow.md

constexpr std::uint16_t IntegerPromotionUB(std::uint16_t x) {
    x *= x;
    return x;
}

// 65535 * 65535 mod 1<<16 = 1

static_assert(IntegerPromotionUB(65535) == 1); // won't compile

Хотя казалось бы в unsigned типах всё надежно..

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

Я чуть выше уже про это ответил.

И как в этой нотации записать не указатель на функцию, а указатель на указатель на функцию, или указатель на указатель на указатель на функцию?

Точно также, как в С, но читается лучше:

op_ref_ref_ref: &mut &mut &mut fn(int, int): int

Разумеется могут возникнуть проблемы с Borrow Checker в такой схеме, так что лучше

op_ref_ref_ref: &mut Box<Box<Box<fn(int, int): int>>>

Хотя я не могу даже представить, зачем нужно передавать "указатель на указатель на указатель на функцию".

Вы правы, тип я забыл указать. Должно быть так:
fn operation(op: fn(int, int): int, a: int, b: int): int { return op(a, b); }

Или можно передать с любым, главное чтобы аргументы совпадали?

Зависит от задачи. Если тип не указан, то ничего не возвращается (аналогично void в С и С++)

Передача аргументом указателя на функцию в С и С++ - громоздкая и архаичная. Например это очень сложно читать:
int operation(int(*op)(int,int), int a, int b) { return op(a, b); }

А вот это сразу очевидно:
fn operation(op: fn(int, int), a: int, b: int): int { return op(a, b); }

Не вижу в этом никакой проблемы.
1) Используйте внутри блока ссылку, тогда перемещение не произойдет.
2) В коде, который возможно не исполнится, вызывайте `.clone()`, если вам нужно владение.
Такой подход будет оптимальным и с точки зрения быстродействия, и читаемости кода.

Какое решение?

Перечитайте раздел с "maybe(async)"

Я так и не понял в чем мораль?

На мой взгляд, лучше разделять библиотеку на 3 части: общая, async и blocking. Изначально немного больше работы, но потом гораздо проще поддерживать.

Я исхожу из своего опыта работы со Stackless Python3, где те же проблемы. Особенно вот эта:

Но, с добавлением этих функций в язык связана одна проблема: они идентичны СИНИМ функциям, поэтому при вызове их невозможно отличить! При работе нужно опираться на документацию и держать в голове все ЗЕЛЁНЫЕ функции, чтобы ненароком не вызвать их из КРАСНОЙ.

Переписываем одинаковый код из года в год и тянем среду выполнения С.

Что же вы предлагаете? Отказ от FFI будет стоить языку жизни, т.к. придется переписать все популярные библиотеки.

Посмотрел подробнее примеры в конце статьи, поля регистров всё-таки есть (тут я был не прав).

А запутали меня строки:
GPIOA->ODR &= GPIO_ODR::ODR[NUM_4] | GPIO_ODR::ODR[NUM_10];

Из которых не следует что поля регистров вообще где-то описаны, или генерятся из SVD файлов.

Думаю это просто неудачный пример, т.к. регистры GPIO не подразумевают нормальных имен полей. Предлагаю эту часть статьи переписать, взяв например регистры и поля RCC. Тогда плюсы автогенерации из SVD будут всем очевидны.

P.S. Теперь ясно, что оно гораздо лучше CMSIS, при условии что вы сами поправите/напишите SVD файлы нужной перифирии.

Библиотека автора пока еще далека от CMSIS даже, т.к. нет работы с полями регистров (имена, R/W и R/O режимы, битовые маски). И совсем не сравнить с библиотеками на Rust, где для полей регистров на уровне типов указывается, есть ли вторичные эффекты при чтении/записи поля.

Но главное, что вендоры пока даже не пытаются исправлять SVD файлы, т.к. ими никто не пользуется. Перепутанные имена регистров, отсутствующая периферия, или наоборот несуществующая, RO поля, помеченные как RW и т.д.

Мало кто готов спуститься до этого уровня и поправить SVD файлы для нужного чипа. А вендоры не готовы принимать исправления. И пока это не поменяется, не возможно сделать автогенерацию кода регистров, и 99% разработчиков будут продолжать писать на С библиотеках вендоров.

В Rust кстати эту проблему решили тем что написали свой стандарт SVD. Ну и пишут с 0 SVD файлы, что довольно трудоемко, хотя они и выходят раз в 8 меньше файлов вендоров.

А я вам написал, что эти фичи eigen делают невозможным выбор оптимального варианта SIMD. И это в С++, где производительность - объект поклонения каждого программиста.

А вот в Rust выбрать можно, ценой некоторого увеличения кода. При этом нельзя (пока) сделать автоматический выбор, как в eigen.

Но вы упорно отказываетесь обсуждать суть проблемы. Кто же из нас демагог?

Я вам развернуто написал что на мой взгляд в eigen хорошо сделано, а что плохо. И чего не хватает в nalgebra и Rust.

Вы же просто заявляете "eigen не выразим на расте", и отказываетесь от нормального обсуждения. Вот это неконструктивно.

По этому возвращаю вам обратно:

Я тоже могу сказать, что embassy не выразим в С++.

И прочитал еще раз. И все-равно мы там обсуждали "другие языки" и GC последние 6 сообщений как минимум.

Пробелмы поставки библиотек в бинарном формате это отдельная проблема. То что в расте это сделать нельзя говорит лишь об ограниченности раста и что он неприменим для вендоров блобов. Хотя скорее всего можно за сишным интерфейсом спрятать реализацию на расте, тогда возвращаемся к той же проблеме.

Разумеется можно:

crate-type = ["dylib", "rlib"]

Будет .so библиотека с кодом Rust без всякого C-API. И для вендоров всё хорошо.

Давайте начнём с того как вендор создаст dll на раст и что вы будете делать с ней?

В dll от вендора на практически любом языке не получится добавить санитайзеры, исходного когда тоже нет.
Так что придется поверить вендору что с ней всё хорошо. И полагаться на гарантии компилятора.
Например для CSharp я уверен что dll не портит память и не вызовет UB. Для Rust аналогично, если вендор мне ответит что там нет unsafe (разумеется если он не врет).

И они рекомендуют переходить на более безопасные языки в целом, а не только на Rust .

Я так понимаю ошибок в 3rd-party на других языках ни когда не бывает? или к чему это?

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

Перечитал. Не согласен.

В чем проблема в С++ делать компиляцию всего дерева из исходников со статической линковкой и нужными флагами санитайзера?

Ага, бороться с зоопарком систем сборки, когда половина зависимостей настроена на динамическую линковку. Реально, но очень долго.

И все же что вы будете делать с dll от вендора?

Вы спрашивали:

а что собственно страшного в переполнении signed int и в чем принципиальное отличие от того что в других языках оно defined behavior хотя и делает тоже самое?

А теперь заявляете:

меня мало интересуют синтетические примеры

Похоже вы не читали другие примеры по ссылке. Вычисление хэша строки тоже синтетический пример?

Ну а в реальной жизни полно уязвимостей, вызванных UB переполнения int, раздел Observed Examples
https://cwe.mitre.org/data/definitions/190.html

А бесконечные циклы и без переполнения знаковых могут случится и не только в С++

В других языках эти ошибки будет легко воспроизвести и поправить код. А в C и С++ UB приведет к гейзенбагу, который будет наблюдаться раз в год при определенном положении Марса в созведии Козерога.

Линуса значит, вот только то что он согласился на поддержку раста как языка для драйверов ни какого отношения к "не безопасности" C++ не имеет, и его претензии к плюсам в целом мне понятны и в большинстве своём обоснованы , но они опять же ни как не связаны с "не бесопасным кодом"

Речь вообще не про Rust. Его претензии к С++ и С привели к появлению опций в gcc, чтобы можно было отключить некоторые UB ключем компиляции.
Ну а про Microsoft и Google вы совершенно случайно забыли ответить.

ты же знаешь что glibc в андроиде на C++ написан? и то что не проблема писать на С++ и иметь при этом внешний апи на C?

Если вот эта, то там от С++ одно название.
https://ru.wikipedia.org/wiki/Bionic_(библиотека)

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

Очнитесь и выгляньте наконец в реальный мир. Он совсем не такой как в 2000 году:

Cloudflare целиком на Rust переписались, в исходниках Android его уже столько же, сколько C, AWS несколько сервисов целиком переписали и не останавливаются (и сделали Firecracker целиком на нем, опенсорс менеджер микровиртуалок, на котором работают Lambda и Fargate), с голенга многие тоже переписываются. Я могу дать полный список известных мне проектов, там от MESA до Figma, Vercel и части бэка npm.js репозитория

Компилятор переносит умножение на 0x20000001 на строку выше. Результат умножения оказывается больше чем int max, и он выкидывает условие остановки цикла.

Если вы перечитаете ветку, то мы обсуждали в основном языки с GC. Кроме того речь шла про санитайзеры, причем тут вообще unsafe?

Конкретно в Rust компиляция всего дерева зависимостей идет из исходников со статической линковкой. И cargo build вам выкачает всё дерево зависимостей, грепайте.

Если же dll это обертка над С или С++, или от вендора, то в ней по определению нечего "грепнуть по unsafe", ведь в С++ никакого unsafe нет.

И тем не менее компилятор Rust иногда размазывает UB по всей программе:
https://hyphenos.io/blog/2023/debugging-ub-unsafe-rust-code/
А вот позиция одного из разработчиков Rust, почему UB это необходимое зло: https://www.ralfj.de/blog/2021/11/18/ub-good-idea.html

Итак я привел вам:
- теорию
- документацию
- реальные примеры
- и даже позицию авторов языка

Вы же пока привели только рассуждения.

Это мы уже обсудили:

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

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

ну предположим нельзя но, хотя мне кажется можно найти нетривиальные кейсы когда CSharp взаимодействует с какими ни будь ресурсами типа COM, но ценой чего? добавления GC? потерями перфоманса или часовыми плясками во круг borrow checker чтоб он соизволил понять что тут всё нормально?

Вы уж определитесь, GC или borrow checker.
Современные GC собирают очень шустро и могут не останавливать потоки для своей работы. Для абсолютного большинства задач это подходит.

Если вам не нравится GC и Rust, выбор довольно мал. Возьмите Zig.

а что собственно страшного в переполнении signed int и в чем принципиальное отличие от того что в других языках оно defined behavior хотя и делает тоже самое?

Конкретно в переполнении ничего страшного. Страшно что это UB, а любое UB может сломать программу максимально странным способом: например конечный цикл может стать бесконечным!
Тут есть и другие примеры:
https://github.com/Nekrolm/ubbook/blob/master/numeric/overflow.md

вот уж чьё мнение меня меньше всего интересует в вопросах "безопасности кода" так это агентства по слежке и созданию 0 day уязвимостей везде где сможет дотянутся.

Мнение Microsoft и Android (Google) для вас тоже ничего не значит? А как насчет Линуса Торвальдса?

в других языках же такого не бывает совсем, привет от Log4j. Но почему то все критически важные узлы чувствительные ко взлому и отказоустойчивости всё равно пишутся на C и С++

Они пишутся по:
1) Историческим причинам
2) Требованиям к FFI: библиотеку должно быть легко подключить к любому языку, так что С, но не С++
3) Требованиям к памяти: нужно гарантировать, что память в памяти не останется важной информации после освобождения объекта

Но процесс идет, и например Android переписывает кучу своего кода с С и С++ на Kotlin и Java, а небольшие критичные куски на Rust.

Ты либо весь код собираешь с санитайзерами либо ни какой, мне трудно представить как собрать половину так половину сяк.

А мне легко. Просто зависимость лежит в dll, которая предоставляется ОС, или хуже того вендором. И попробуйте туда внедрить санитайзер.

И мы возвращаемся к тому, что вам надо пройти по всему дереву зависимостей и все их перекомпилировать с санитайзерами и другими защитами. И надеяться что ничего не сломается.
В моем текущем проекте например 11 прямых зависимостей и 312 всего, нереально.

Information

Rating
2,748-th
Location
Ижевск, Удмуртия, Россия
Date of birth
Registered
Activity