Comments 86
Исходя из benchmarksgame.alioth.debian.org/u64q/rust.html, пока Rust'у еще далеко до С++.
Язык должен быть «безопасным» в меру. Нужны просто прямые руки. Еще и статические анализаторы помогут.
И еще — почему синтаксис Rust не С-подобный? ИМХО, не правильно позиционировать его как замену С++.
Нужны просто прямые руки.
Эх, если бы всё было так просто.
ИМХО, не правильно позиционировать его как замену С++.
Исключительно из-за синтаксиса?..
Исходя из benchmarksgame.alioth.debian.org/u64q/rust.html, пока Rust'у еще далеко до С++.
Я бы только из подобных соревнований столь суровых выводов о языках не делал :)
почему синтаксис Rust не С-подобный?
Очень даже си-подобный. Конечно, зависит от того как определять это понятие, но вот под эти требования — http://dic.academic.ru/dic.nsf/ruwiki/249655 — вполне себе подходит.
Ну и ИМХО, синтаксис Rust слишком уж С-подобный, можно было и полаконичней
Ну и ИМХО, синтаксис Rust слишком уж С-подобный, можно было и полаконичней
Как я понимаю, команда разработки решила слишком далеко от привычного большинству целевых программистов сишного синтаксиса не уходить, потому что язык и так сложностей в начальном обучении порядочно вызывает, а если еще и синтаксис будет непривычный — 100% в массы не пойдет.
Rust "кушает больше" памяти из-за особенностей jemalloc — аллокатора. Если быть точнее, он не кушает больше — просто при старте jemalloc резервирует довольно большой пул под свои задачи по умолчанию. Т.е. этот "отжор" константный и к коду на русте прямого отношения не имеет.
Во-первых, на стабильной ветке уже можно собраться с системным аллокатором.
Во-вторых, обсуждение большого стартового пула jemalloc было, и меры собираются принять. К сожалению, ссылку сейчас не найду.
Да, памяти жрёт больше, тут ничего не поделать
Я вот не уверен в этом так уж сильно, особенно если речь идет не о компактных синтетических тестах, а о реальных программах. За счет чего ржавчина должна "жрать" сильно больше памяти?
Когда-то аналогичный вопрос задавал и аргументом было то, что в расте "ссылки жирнее" (речь о трейт-объектах): в плюсах ссылка это просто один указатель, а дополнительный указатель на таблицу виртуальных функций лежит в объекте, а не в самой ссылке, в отличии от раста.
Но я как-то сомневаюсь, что данное различие большую роль играет. И уж точно её не должно быть в число-дробилках: там статическая диспетчеризация будет везде где можно.
Отвечал в соседней ветке, чуть выше. Несколько месяцев назад натыкался на возмущения по поводу того, что Rust кушает на синтетиках сильно много памяти. Вкратце, оказалось что jemalloc при запуске выделяет большой пул. Т.е. к тому, сколько "кушает" Rust, это не имеет прямого отношения. Переключаемся на системный аллокатор (уже можно) — и имеем паттерн работы с памятью как в C++.
Если нет, не доступны — это уже чуть более адекватно, как по мне, ведь проверяется в том числе и качество реализации, которое подразумевает наличие возможности спуститься и на более низкий уровень.
Простите, а если я в данном тесте из кода на Питоне «спущусь и на более низкий уровень» и вызову библиотеку на Си, это будет «уже чуть более адекватно»?
В динамически типизированных языках добавляется информация о типах, что увеличивает расход памяти не более чем в константу раз. Для сборки мусора и рефлекшена требуется некоторая дополнительная информация, но очень незначительная.
Но все это к Rust не относится.
В Rust, по сравнению с C++ в объектах нет ссылки на vtbl — то есть экономия. Но эта ссылка добавляется к ссылкам на объект не известного на этапе компиляции типа — здесь некоторый проигрыш. Не очевидно, что перевесит, но разница не будет значительной.
Текущая реализация Rust проигрывает по размеру исполняемого файла из-за включения библиотек. От этого можно избавится, но надо приложить заметные усилия. Но размер бинарников сейчас все равно сильно меньше размера прилагаемых к ним данных.
Небольшая добавка. Любой кто жалуется на большой размер бинарников в русте может сделать статически слинкованную программу на C++ — и посмотреть на размер. Была статья (перевод был на днях на хабре), где разбиралось, почему Rust делает такие толстые бинарники.
По вопросу же Vtbl. У Rust есть в этом плане киллер-фича — явный полиморфизм. Если Trait Object — значит динамика.
Тонкая отсылка к https://habrahabr.ru/post/281370?
Ну и еще интересно было бы если линк на код в статью вставили чтоб можно было полюбоваться
а чего такого можно в mp4 демуксере затолкать чтоб сломать парсер?
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3870
линк на код
https://github.com/mozilla/mp4parse-rust
в статью вставили
Обе ссылки из текста статьи :)
Вместо того чтоб нормально написать парсер переписать писать его на другом языке? А как же отладка кода (если это не gdb)? В VisualStudio нельзя будет пройтись по парсеру как будто это какой-то массивный opengl что ли?
Детали того «CVE-2015-3870» не читаются.
Я так понимаю, речь об этом и всяком что гуглится по запросу "android stagefright exploit".
… немного удивился что кто-то умудрился в андроид закомитить код который парсит что-то без валидации размеров
Люди время от времени ошибаются или забывают что-то сделать, так было и всегда будет :( .
Вместо того чтоб нормально написать парсер переписать писать его на другом языке?
Я думаю, что те ошибки, которые уже нашли, тут же исправили и выкатили обновления. Вопрос в том, сколько подобных уязвимостей еще не известны авторам, но известны злоумышленникам.
А ржавчина позволяет на порядок уменьшить возможность возникновения подобных косяков (совсем без unsafe на каком-то уровне и без ffi писать реальный код все-таки нельзя).
А как же отладка кода (если это не gdb)? В VisualStudio нельзя будет пройтись по парсеру как будто это какой-то массивный opengl что ли?
Отладка это отладка, как она уязвимости должна помогать находить?
А в чем проблема к примеру использовать тогда custom C++ array with checked index bounds? Вроде как vector::[] calls vector::at()? Подобная run-time проверка тоже будет.
на счет отладки: если трудно пройтись по коду в отладчике это уж точно не поможет в отладке этих самых уязвимостей и прочих проблем короые могут привести к букету других проблем и уязвимостей.
«android stagefright exploit» — там в основном все про stagefright, только частично упомянается мп4 парсер, который меньше 5% от stagefright занимает.
Ну тогда я бы и сам не отказался от ссылок на подробности :(
Сам мп4 парсер довольно таки легко написать без подобных проблем (для тех кто знают структуру мп4 это очевидно).
Каюсь, я структуру mp4 не знаю и мне не очевидно. По моему опыту правильно написать хоть немного объемный код на плюсах, который работает с данными из недоверенного источника, очень сложно.
А в чем проблема к примеру использовать тогда custom C++ array with checked index bounds?
Можно, главное везде это последовательно делать (и аналогичную остальную опциональную защиту использовать). А я считаю, как выше написал, что все люди время от времени ошибаются и что-то забывают, так что рутину с человека надо максимально перекладывать на программу. И вот в ржавчине по умолчанию все безопасно и без UB — ты должен специально попросить компилятор если что-то опасное хочешь сделать. А в плюсах наоборот и без UB реальную программу больше сотни строчек написать практически нельзя.
Вроде как vector::[] calls vector::at()? Подобная run-time проверка тоже будет.
Насколько я помню, что бы была проверка границ у плюсового вектора надо дергать метод at
, а не обычный оператор индексирования.
если трудно пройтись по коду в отладчике это уж точно не поможет в отладке этих самых уязвимостей и прочих проблем короые могут привести к букету других проблем и уязвимостей.
Я не очень в курсе как там сейчас ситуация с отладкой в VS, вроде как подвижки какие-то есть, но в целом так себе работает. IDE для ржавчины и всякие мощные плагины для редакторов вообще пока в состоянии активного развития, тут время нужно.
А в отладчике пройтись по коду не трудно — gdb-то поддерживается.
Отладка уязвимостей, кмк, обычно аналитическая и отладчик тут вообще не нужен — главное узнать о уязвимости. А узнать отладчик никак не поможет, тут скорее статический анализатор нужен.
Подробности «android stagefright exploit» или о том что мп4 парсер меньше 5%? stagefright это что-то вроде directx в андроиде, новая мультимедиа подситема заменившая старый медиа код от On2. Сам Mp4 формат нерально тяжелый, но в андроиде он в очень урезаном варианте, как вропчем и везде — mp4 формат нигде толком полностью не написан кроме возможно mp4box. Для обычного проигрывания mp4 или 3gp файлов достаточно маленького сабсета от формата mp4. В кратце формат состоит из «коробок» которые имеют подобную структуру: box = [size][data of size bytes], file: [box][box]...[box], некоторые коробки содержат другие коробки и тд, но ВСЕ они указывают размер данных и все. Есть там всякие ньюансы (32/64-бит size, 0-size и тд) но это все мелочи. Есть пару коробок которые имеют разную структуру в зависимости от того кто файл делал, но все это легко решаемо если код пишется тем кто знает что делает. Поэтому я просто не пойму как переписывание mp4 в другом языке может чем-то помочь, так как скорее всего проблема не в парсере а в том что в коробки засовываются битый bitstream который уже потом взрывает, либо там offsets не правильные указываюся (в коробке-таймлайне) или код который читает коробки с codec-specific-data, но их очевидно что надо проверять а не слепо читать и парсить без оглядки.
> По моему опыту правильно написать хоть немного объемный код на плюсах, который работает с данными из недоверенного источника, очень сложно.
Смотря где. В мп4 парсере нужно написать код для поддержки может 20-ти разных типов коробок, но все они имеют одну и ту же базовую структуру: [размер][данные], т.е. это в базовом классе проверка делается один раз и все.
> Насколько я помню, что бы была проверка границ у плюсового вектора надо дергать метод at, а не обычный оператор индексирования.
Да, именно так. Я имел ввиду что-то вроде этого:
struct xvector: vector<uint8_t>
{
uint8_t& operator[](int pos){ return at(pos); }
};
так как stagefright на С++ написан, класс буфера заменить на xvector и будет оператор[] с проверкой. Mp4 парсер не требует больших мощностей, вот в декодере уже не получится такое делать, там реально в многих местах (как FFT например) все регистры уже под завязку загружены, да и ко всему там часто уже HW-декодеры в зависимости от кодека.
Подробности «android stagefright exploit» или о том что мп4 парсер меньше 5%?
Скорее о том, почему именно этот компонент решили переписывать, хотя про mp4 было интересно почитать, спасибо :). До этой новости я вообще думал, что в серво быстрее попадет https://github.com/servo/rust-url, но с его внедрением какие-то затруднения возникли внезапно.
но их очевидно что надо проверять а не слепо читать и парсить без оглядки
Мне представляется, что почти все серьезные уязвимости можно сопроводить словами "очевидно, тут надо было просто ..." — иногда человеки просто забывают где-то сделать что-то очевидное.
Поэтому я просто не пойму как переписывание mp4 в другом языке может чем-то помочь
Мне сама по себе разработка серво мало интересна — только как самый крупный проект на ржавчине, который и держит ее сейчас на плаву — так что я не слежу за подробностями ржавого браузеростроения и теперь не могу нагуглить конкретные причины создания и внедрения mp4parse-rust, видимо обсуждение было внутренним :(
Может конкретно этот компонент переписали просто потому, что его было просто переписать и надо уже начинать протаскивать ржавчину в огнелиса, вполне допускаю.
Ох блиа, теперь ещё один компилятор портировать...
Ваш target не поддерживается llvm? Или вы таки про libstd, а не компилятор?
Ваш target не поддерживается llvm?
Это верно.
Кстати, про foreach: а можно ли в Rust устроить грабли с изменением размера вектора в то время, пока по нему идет итерация?
При использовании индексов есть проверка на выход индекса за границы массива (bounds check) в рантайме. Да, есть небольшой оверхед, но тут решили в сторону безопасности. Используете итераторы побольше, чтобы таких проверок избежать.
- Нет, такого сделать нельзя, борроу чекер при компиляции не пропустит.
Получается, что какой-нибудь FFT на Rust писать скорее всего не имеет смысла (хотя кто знает, вдруг возможно тот же FFT эффективно написать, используя хитрые итераторы вместо доступа по индексу).
Есть еще get_unchecked и get_unchecked_mut, если уж очень надо, но их надо в unsafe заворачивать.
В foreach нельзя будет поменять вектор, потому что он будет «взят» циклом как неизменяемый, и компилятор это прямо запрещает.
Unsafe есть, он позволяет делать много не безопасных штук. Но для алиасинг обычных ссылок всё равно не даст сделать, нужно будет ещё кастить явно в сырые указатели, да не по одному разу (чтобы ещё немутабельность убрать). В общем обойти проверки безопасности можно, но довольно сложно, проще этого не делать и писать безопасно.
Ее компилятор либо вырезает (если это цикл по массиву), либо она есть и это просадка по скорости раза в 1.5 на очень простых циклах.
Кстати, про foreach: а можно ли в Rust устроить грабли с изменением размера вектора в то время, пока по нему идет итерация?
Как уже сказали, с честным циклом по массиву — нельзя, но на всякий отмечу, что при использовании явного индекса магии не произойдет:
https://play.rust-lang.org/?gist=43a890e5ead474df1c66ce25894b7e49
let mut a2 = vec![1, 2, 3];
for i in 0..a2.len() {
println!("f2: {}", a2[i]);
a2.truncate(1); // коварно уменьшаем размер массива
}
...
thread '<main>' panicked at 'index out of bounds: the len is 1 but the index is 1'
Нельзя.
Что нельзя? О.о Вон же ссылка на плейпен.
Итератор заимствует объект по константной (читающей) ссылке. Компилятор запрещает иметь одновременно чтение и модификацию сущностей. Это контролируется на этапе компиляции.
Спасибо, я в курсе :) При использовании явного индекса (что иногда бывает полезным при работе с массивами) одновременного заимствования массива может и не быть, тогда ошибка произойдет уже только во время работы программы.
Погоди, но взятие по индексу ведь занимает массив, так что так просто его не модифицируешь, если где-то сохранились ссылки на значения, взятые по индексу. Или ты про что?
Я же пример кода прилепил)
Я про случай, когда мы сначала узнаем длину массива, а потом старым добрый сишным циклом с "ручным" индексом (язык этого не запрещает же) по нему проходимся — в такой ситуации никакого одновременного заимствования может и не быть.
заголовок:
"Код Rust включен в Firefox 48"
ну это ожидаемое поведение
Не спорю.
многие не слишком четко понимают, что rust гарантирует и чего он не гарантирует
Из-за этого, собственно, и написал.
Rust гарантирует, что программа не будет работать в случае классического сишного undefined behavior
Это еще с оговоркой про unsafe — при его неаккуратном использовании много что может пойти не так :(
upd: промазал, ответ на https://habrahabr.ru/post/305536/#comment_9698750
— Я сделяль часть ФаерФокса на Руст.
— Ок, здорово, но зачем? Просто потому что мог? Что это дало ПОЛЬЗОВАТЕЛЯМ? Браузер стал быстрее запускаться? Быстрее работать? Отжирать меньше памяти?
— Но… но… я сделяль код на Руст который не крашит ФаерФокс
— Ок, здорово, но на C/C++ тоже можно писать код который не будет крашиться.
Так в чем смысл был? Банальная фаллометрия?
Что это дало ПОЛЬЗОВАТЕЛЯМ?
От самого факта переписывания этого компонента на ржавчину пользователям и правда прямо сейчас прямой выгоды нет (как и вреда).
Смысл в самом прецеденте — Ржавчина пробралась в стабильную ветку такого большого проекта. Для начала в небольшой компонент, но надо понимать сколько за этим стоит работы по подтягиванию инфраструктуры Ржавчины до нужного состояния (на андроиде вон до сих пор добивают) и адаптации сборки самого Firefox.
Т.е. это реальный и значительный шажок к будущему, когда процент ржавого кода сильно вырастет и уже это позволит добиться более быстрого времени запуска, лучшей производительности и меньшего потребления памяти.
на C/C++ тоже можно писать код который не будет крашиться.
Предполагается что на Ржавчине это делать проще, особенно в больших масштабах.
Руст
Раст
Ок, здорово, но на C/C++ тоже можно писать код который не будет крашиться.
Наверное, смысл в том насколько больше/меньше для этого усилий требуется? (:
Оставить код = ноль усилий.
Переписать нафиг = овер9000 усилий.
Л — логика.
Логика в том, что плюсы — плохой инструмент (по крайней мере с точки зрения Мозиллы, иначе бы они разработку Ржавчины не оплачивали) и его постепенно заменяют на лучший инструмент — ржавчину. Да, поначалу это проносит мало прямой выгоды для пользователей, но в долгосрочной перспективе должно быть для них выигрышно.
не крашился
Можно подумать это единственная проблема плюсового кода.
А я правильно понимаю, что из-за этого теперь во всех линуксовых дистрибутивах (файерфокс же, наверное, практически во всех есть, кроме совсем уж узко специализированных) будет более-менее свежий стабильный rustc/cargo?
скорее менее, чем более
Как минимум, 1.8 должен быть. Значит и дистрибутивам, что бы нормально собрать фаерфокс придется хотя бы такой же запаковывать.
В любом случае это не очень важно, так как есть rustup
Не критично (хорошо хоть оно уже давно "curl… | sudo sh" не требует), да, но мне массовое использование rustup видится временной мерой. С течением времени хотелось бы ставить cargo/rustc как обычный gcc — из пакетного менеджера, а не где-то сбоку.
1.8
Откуда я 1.8 взял? 1.10 текущая стабильная же.
Ну в арчике из оф.реп ставится стабильный раст и карго. Растап нужен для найтли и бет разве что.
Код Rust включен в Firefox 48