Комментарии 470
уязвимости будут всегда, пофиг какой язык
Если язык способствуют созданию ошибок, то количество уязвимостей всегда будет больше, чем если используется относительно безопасный язык. Даже у очень умных и опытных программистов.
DROP DATABASE;
как значение поля и выполнится.ExternalString userInput = myWebSocketClient.receive();
InternalString query = "SELECT password FROM `users` WHERE username = " + userInput;
myDatabase.query(query);
Компилятор рассказал ему, что нельзя конкатить ExternalString и InternalString, на что программист ответил «ну ладно» и написал
ExternalString userInput = myWebSocketClient.receive();
InternalString query = "SELECT password FROM `users` WHERE username = " + (InternalString) userInput;
myDatabase.query(query);
Вот и уязвимость.
Добавление (InternalString)
само произошло, или все-таки программист намеренно написал? Кто-то просто напишет, а кто-то задумается и поищет информацию, почему возникает ошибка, и найдет что конкатенировать внешние данные с внутренними приводит к инъекциям. То есть это уменьшает вероятность появления инъекции в коде на этом языке. Низкоквалифицированные программисты низкоквалифицированны потому что не знают, а не потому что специально вносят баги. А если компилятор ничего не говорит, то и нет повода что-то узнавать.
Кто-то просто напишет, а кто-то задумается и поищет информацию, почему возникает ошибка,
Один то может задумается, а потом придет «обезьянка» и тупо у себя в коде точно так-же нафигачит, потому что Большой Тим Лид тоже ваяет именно так. Это никак не решает проблему.
А еще обезьянка может по умному совету со StackOverflow rm -rf / куда-нибудь вставить.
sudo только не забудьте.
Естественно, делал.
Более того, недавно я даже стал этому свидетелем)
Но это же не повод отменить разграничение прав?
Аналогично, возможность понаделать небезопасных кастов не повод отказаться от защиты от инъекний на уровне типов.
Но при прочих равных условиях (в т.ч. квалификации программистов) на условном C уязвимостей будет больше, чем на условной Java.
Можно попытаться сравнить число уязвимостей в проекте, написанном супер-профессионалами на C с числом уязвимостей в проекте, написанном средними программистами на Java. Тут непонятно, как выйдет. Но те же супер-профессионалы, перейдя на Java, допустят меньше ошибок, чем сами же на C.
[зануда_mode on]
Напомню, что в любом реальном проекте на сотню тысяч строк уязвимости точно есть. Вопрос только в количестве и трудности поиска.
И да, сторонние библиотеки точно так же содержат уязвимости и, вообще говоря, их строки надо добавлять к строкам проекта. Они могут быть лучше написаны и протестированы, и ошибок в них может быть меньше, но в достаточно объемной библиотеке они точно есть.
[зануда_mode off]
Есть вкладки-фильтры данных
spectrum.ieee.org/static/interactive-the-top-programming-languages-2018
P.S. Что не удивительно выводит на пик популярности язык программирования Python.
Зато спасет от memory unsafe.
Что за глупость заморозить язык на десятилетия, я этого совершенно не понимаю.
Столько очевидных источников ошибок.
Си и С++ стоило развивать в тандеме, чтобы не терялась обратная совместимость, но при этом было развитие и устранение врождённых недостатков.
А что Вы думаете по этому поводу?
Я тоже, как и этот Гейнор, борец за всё хорошее против всего плохого,
и точно знаю, что лучше быть богатым и здоровым, чем бедным и больным.
Экономика? Не, не слышал.
1) Про вред курения. Если сравнивать курение человека, который живет на природе в чистой среде и питается исключительно чистыми продуктами (иных нет), живя далеко в Сибири, в Африке и т.д. с человеком, который ни разу не курил в жизни, но живет через дорогу от металлургического комбината, хим.завода или даже все вместе. Про всякие тепловые электростанции молчу. То я бы не сказал, что курение вредно, оно даже может быть полезно, вроде прививок, при количестве 1-2 сигареты в месяц или год. Особенно, если человек из природной среды поедет к человеку города или живущему рядом с промышленностью. так сказать — заблаговременная подготовка к нахождению в опасных условиях.
Был даже забавный случай, когда некоторых знакомых пытались убедить бросить курить, аргументируя вредом здоровью. Особенно смешно звучало для металлургов и сварщиков, особенно для сварщика, который варит без какой либо защиты для органов дыхания. Покупка защиты отложена до лучших времен, а сейчас банально з/п не хватит, ныне платят за такой труд всего лишь около 6 тыс руб (инфа 2-х летней давности по з/п, но я не слышал о кардинальных подъемах з/п).
2) про воду. Скоро бутилированный воздух будут продавать. А, нет, уже продают. Немного глупо, т.к. проще взять баллоны кислорода, азота и потихоньку выпускать в изолированном пространстве. Или с водой — дистиллированную + минеральные добавки (тот же магний). Или вообще провести чистый газ — и можно получать углекислый газ (который питание растением, а не для грантоедов глобального потепления) и воду. В природном газе различные добавки, а вот производить метан на электространциях — это одновременно будет и хорошим аккумулятором, т.к. инфраструктура уже есть, это не с водородом, для которого инфраструктура только строится. Мало того — углекислый газ не является ядовитым для человека, мы им вообще дышим, хотя и не чистым, а газом с содержанием углекислого газа — доли процента.
Отсюда — приходим к известному «все лекарство и все яд. Зависит от дозы». Слишком много с/с++ стало ядом, причем на подобии медленно действующего токсического яда. В небольших дозах незаметен, а позже ошибки накапливаются и могут вызвать смерть пациента (тут ссылку про разорение кого-либо из-за ошибки программиста)
2) С выпусканием воздуха скорее проблема в том, что в существующем в городе есть процент нежелательных примесей. Скажем, угарного газа в воздухе 40 мг/м3 (вдвое выше ПДК). Чтобы заменить половину воздуха в комнате 20м2, надо выпустить ~62 кг смеси азота с кислородом (на самом деле больше, т.к. выходить из комнаты будет смешанный воздух, где есть и чистый, и «грязный»).
В общем, не очень практичный метод — слишком много его надо привозить очищенного.
Лучше продвигать очевидную истину, что курильщик при прочих равных глупее, безвольней, больнее, беднее.
Ух, сейчас курильщики набросятся на объективную реальность! Наркотик давит на мозг.
Важно заставить всех перейти на хорошую воду
Важно заставить
Зачем заставлять?
А в том смысле, что если все вокруг используют воду из-под крана, хочешь не хочешь ты будешь пить такую воду, например через суп в ресторане. Если только не жить в полной изоляции и не делать всё собственноручно.
Есть санитарные нормы. Вряд ли можно ожидать что-то лучше них, если не брать випобслуживание. Надеяться на культуру можно, но не ясно, как это могло бы выглядеть. Промышленный фильтр в ресторане? Это возможно, но без требования санитарных норм всё равно каждый второй владелец будет игнорировать.
Расходы же.
Важно заставить всех перейти на хорошую воду
Вот например, спирт этиловый и спирт метиловый. На запах/вкус/цвет одинаковы, даже эффект по началу одинаковый…
Ну тут вопрос философский. Что такое натуральный ароматизатор и идентичный натуральному? И то и то химия. Где-то все лишнее убрали или где-то все нужное добавили.
К слову, на «С++, идентичный натуральному», действительно, тоже ложится. Всякие rust'ы и swift'ы, конечно, здорово, — а с производительностью там что? Не в масштабе поделки-микросервиса, а по-больше и по-ответственнее. Взять то же ядро линукса: сетевая подсистема, менеджер памяти — как они себя поведут?..
Хм… Вариантов больше чем два. Вода из-под крана фильтрованная. Вода из-под крана кипяченная. :) бутилированая тоже может быть из крана с нашлепкой "из артезианского источника на глубине пяти километров".
А какую воду вы предпочитаете пить? Дешёвую – из-под крана, или значительно более дорогую – бутилированную?
Там где я живу, вода из под крана — качественная. Так что бутилированная мне дома не нужна.
А есть районы города, где вода из под крана — ржавая и им приходится пить бутилированную и на ней же готовить еду.
Экономика? Не, не слышал.
Статья формулирует проблему, которую не решить — переписать код ядра *nix. По человеко-часам это займёт приблизительно… лет 30, при том, что текущее ядро параллельно с этим не перестанет развиваться.
Весь сыр-бор в первую очередь из-за утечек данных, а часть индустрии на это клала. Образование (те же школы), медицина (кроме данных пациентов), многие бюрократические организации (особенно на просторах СНГ). Еще есть те, у которых компьютеры к сети просто не подключены.
Кстати, мы решали проблему с УЗИ аппаратом. Врачи хотят в него втыкать флэшки, а куст реестра в 2000 имеет ограничение, по-моему, 64МБ, иначе система падает в BSOD. Решение: регулярно чистить раздел с подключенным когда-либо устройствам.
С точки зрения же безопасности… Ну, есть «золотой» образ системы, снятый механизмом типа ghost/acronis. Ну, и всегда такие штуки нужно защищать по периметру снаружи, т.к. в них самих почти наверняка настройка файрволла и т.п. запрещена.
Самому было лень настраивать полноценно подобные компьютеры на волонтерских началах. Поэтому со временем туда и вирусы попадали, и всякие игры устанавливались третьими лицами.
По человеко-часам это займёт приблизительно… лет 30
То бишь, 30 разработчиков справятся за год? И не надо только про 9 женщин и ребенка за месяц, ок?)
Если этот год не будут спать, есть и как-либо отрываться от кода, при этом зная Pure C, Rust, архитектуру ОС и архитектуру ВМ и сетей и частное — отдельные конкретные реализации и воркараунды для железячных мест, где воркараунды нужны и почему на уровне способности "читать и писать без подсказок в 90% случаев и знать где быстро найти для остальных 10%" — то да, года будет достаточно. Утрированно, конечно, у каждого из этих тридцати своя нечеткая специализация, и 90% можно даже превратить в 70%, уух, задачу облегчили уже! Четкой специализации для команды в 30 человек не нужно, но понятие о всех остальных отраслях у них должно быть. Найдете 30 таковых по всему миру?
"Переписали" — всё же громко сказано, это был PoC операционной системы на Rust, сделанный с нуля и после этого уже несколько раз переписанный с пониманием "как делать не надо". Изначально Redox позиционировался как игрушечный проект и на вопрос "это замена Linux?" авторы давали определённый отрицательный ответ.
Добро пожаловать в Android. Одни проблемы решились, другие появились.
Я думаю, нужно начинать переписывать *nix и другие критически важные для сети вещи на Rust.
https://people.mpi-sws.org/~dreyer/papers/rustbelt/paper.pdf
http://plv.mpi-sws.org/rustbelt/
Отлично. Раст — формально верифицированный язык.
Rust не может быть верифицирован на данный момент, потому что у него даже спецификации нет.
То, что верифицировано в этой статье, это некоторое пожножество системы типов Раста, как его понимают авторы статьи.
Если говорить о реальности, то известно, что Раст в текущей реализации небезопасен (содержит десятки "багов", самому старому из которых >5 лет).
Так что ситуация хоть и несравненно лучше, чем с C и C++, но далека от той идиллии что рассказывает Rust-пропаганда.
Мы работаем над этим. А как у C++ дела?
Прокомментирую расхождение в наших комментариях, чтобы не думали, что у нас разброд и шатание.
Конкретно в https://people.mpi-sws.org/~dreyer/papers/rustbelt/paper.pdf формально доказывается, что система типов Раста, владение, заимствование и прочее — корректны. Доказывается, что программа безопасна, если написана на безопасном подмножестве Раст. Доказывается, что программа безопасна, если в ней есть вкрапления unsafe
, в которых программист не допустил ошибки, UB.
Кроме того, проект RustBelt на текущем этапе занимается формальной верификацией библиотеки std, но полная проверка требует времени. Поэтому библиотеку проверяют по кускам. Да, были найдены и исправлены 2 ошибки в unsafe коде (что показывает, что ребята делом занимались), тем не менее все эти thread, mutex, Arc/Rc формально безопасны.
Чтобы решить проблему, поставленную в статье, нужно верифицировать не раст, а программы, на нём написанные.
Давайте я подробнее распишу свою цитату:
Доказывается, что программа безопасна, если написана на безопасном подмножестве Раст. Доказывается, что программа безопасна, если в ней есть вкрапления unsafe, в которых программист не допустил ошибки, UB.
Эта означает, что формально доказано, что в программе, написанной на Rust без unsafe
, отсутствуют проблемы с памятью, нет use after free, нет buffer overflow, то есть всех этих memory unsafety. И гонок данных тоже нет.
Проверка всех правил и контрактов в блоке unsafe { }
ложится на плечи программиста. Потому что unsafe означает: заткнись, компилятор, я знаю, что я делаю, хватит меня поправлять. Никто не запретит вам вызвать два раза подряд libc::free
на один и тот же указатель, вопрос в том, что ручное освобождение с помощью free
возможно только внутри unsafe
.
И тут мы приходим к статистике: в 99.9999999% случаев вам не понадобится ручное управление памятью в Rust (ну прям как в CppCoreGuidelines, используйте RAII). В 99.9999999% случаев вам не нужен unsafe
. А если он и нужен, то он строго локализован (иначе на ревью надо отрывать руки). unsafe
— это явное ключевое слово, его можно грепать по проекту, на него можно настраивать триггеры, любое появление unsafe
в проекте — эпохальное событие, которое необходимо проверить. Ибо внутри unsafe
можно выстрелить себе в ногу. И люди стреляют. Надеюсь, вы понимаете разницу между двумя проектами в 300 KLOC, но один написан на Rust с 1 строчкой unsafe
, а второй написан на C++. Как говорится, happy debugging.
Большинство проблем в коде, который пишут прикладные программисты.
Ну это правда, и Rust не позиционирует себя как язык, защищающий от int getRand() { return 42; }
. Он защищает от целого класса ошибок, связанных с памятью, что доказано формально, т.е. математически =)
От логических ошибок не защищает =)
Я надеюсь, вы понимаете разницу между формальной верификацией конечных программ, формальной верификацией компилятора и формальной верификацией системы типов языка?
Хотя, возможно, мы просто по-разному парсим исходный вопрос этой ветки. Он неоднозначен.
Да, вы правы. Необходимо уточнение исходного вопроса.
aeeneas, не могли бы вы уточнить, что вы имели ввиду под:
Как там у Rust с формальной верификацией?
Ну переписывай. В чём проблема?
Тут JS может из браузера вломится в соседнюю вируальную машину. Тоже С++ виноват?
Может архитектуру безопасности ОС пересмотреть, раз такие косяки ОС допускает сделать?
Давайте сразу так:
Кроме того, большинство микропроцессорных архитектур, даже самых важных для безопасности Интернета, не являются новыми. Они были запущены десят лет назад, если не больше. X86 например, более тридцати лет. И они не разделяют команды и данные «memory unsafely». Для масштабных проектов, подобных этим, замена всего оборудования потребует десятки лет…
Я понимаю, им надо пиарить rust, но все же современный C++ далеко не так плох, как его описывает автор. Другое дело, что адаптация новых стандартов идет медленно. Но все равно, куда проще плавно перевести код с C++98 на C++17, чем на rust.
Ну а C — там да, нужно только по спец разрешению пускать людей писать на нем код, только с десятикратным code review. Тк за кажущейся примитивностью и понятностью языка, скрывается возможность понаделать таких ляпов…
Ну, просто английское «adoption» — действительно плохой друг переводчика.
Насчёт «проще перевести на С++17»… Спорно. Зависит от объема проекта.
Шаблонно (т.е. автоматизированно) это все равно не сделаешь. А выгоды какие? Только переиспользование существующего кода?
Русский у меня, хоть и родной язык, на данный момент — далеко не самый используемый мной, так что бывают такие вот "англицизмы" в моей речи.
Про C++17 — как минимум 3 из 4 названных основных проблем, указанных в статье, за исключением целочисленного переполнения, в современных плюсах проблемами не являются.
Сам по себе, конечно, переход от C++98 ко всяким там умным указателям, лямбдам, итп — задача не из тривиальных. Уж тем более с учетом того, что нельзя перевести только часть проекта на те же умные указатели, да конкретного типа объектов. Либо все, либо ничего. Плюс придется еще поотдавливать всякие возможные циклические зависимости. Но по своему опыту скажу, стабильность кода, даже от простого перехода на умные указатели, поднимается в разы. Ну а более современные фишки, вроде той же move semantic, позволяют проводить оптимизации, которые раньше можно было сделать только хардкорно, вручную.
в современных плюсах проблемами не являются
Ну не прям так категорично. Уверен, что в условиях многопоточности, все эти проблемы все равно всплывут даже если прям вообще все на stl и умных указателях. Решаются такие вещи только кардинально — либо как раст, либо сборщиком мусора и кучей компиляторных вставок с проверками, где вообще любое действие с памятью обернуто в безопасную конструкцию. Даже целочисленное переполнение будет уже не страшно, т.к. сработает проверка выхода на за границы.
адаптация новых стандартов идет медленно.
Адаптация, простите, к чему?!
Я понимаю, им надо пиарить rust, но все же современный C++ далеко не так плох, как его описывает автор.
Именно настолько плох. Чего стоит только нескончаемый перечен CVE, в котором встречаются слова «buffer overflow», «double free», «use after free»,…
Другое дело, что адаптация новых стандартов идет медленно. Но все равно, куда проще плавно перевести код с C++98 на C++17, чем на rust.
Если хотя бы новый функционал не писать на С и С++, то это уже будет большой шаг вперед. Но для этого нужно признать, что виноват язык, а не глупые программисты, которые не умеют писать без ошибок.
Если хотя бы новый функционал не писать на С и С++, то это уже будет большой шаг вперед. Но для этого нужно признать, что виноват язык, а не глупые программисты, которые не умеют писать без ошибок.
Могу сказать, что разница в 50 раз на производительности, в зависимости от того как вы напишете код того стоит. Напишете 100% безопасно с «автоматикой» — будет x1, напишете грамотно с «ручным управлением» — будет x50 скорость.
Да во втором случае придется немножко почитать логи на предмет утечек памяти в отладке и протестить корректно. Да, для этого нужна квалификация.
Но С++ то тут причем ?!
Нефиг браться мокрыми руками за оголенные провода под напряжением. Они от этого ржавеют…
Напишете 100% безопасно с «автоматикой» — будет x1, напишете грамотно с «ручным управлением» — будет x50 скорость.
Есть ссылка откуда такие числа, особенно в контексте Rust'а?
Могу сказать, что разница в 50 раз на производительности, в зависимости от того как вы напишете код того стоит.
В 50 раз? Если не брать в расчет встраиваемые системы, то какая реальная программа для центрального процессора работает в 50 раз быстрее, чем программа на .Net/Java?
Не синтетическая, а именно реальная.
Даже синтетика настолько не отличается
2005/6 год. Notebook CPU Core2Duo и Ram 4 GB DDR2.
Алгоритм кеширования (нюансы не помню) и цель была выжать максимальную производительность.
С++: Замена double на double* и _smart_ptr на IFn* в сигнатурах функцияй ну и управление памятью (изменено были на ручное new/delete) при сохранении алгоритма.
Сам удивился результату. Сейчас, думаю, результат будет поскромнее. Надо будет проверить на досуге.
Просто как пример привел.
В том же С++ или любом другом языке может быть задача с кучей обрабатываемых данных, причем разных структур и промежуточных, с долгой обработкой, а не раз 1 алгоритм запилил и оптимизий. Очень часто данные надо гонять, и объекты в доменной области есть.
Что до юнити — да можно переиспользовать игровые объекты классически — чтоб не создавать каждый раз новый, но речь не только об этом.
Вот например есть либа для триангуляции, вот она при написании на Си имела производительность Х, потом при переписывании на С++ стала Y, потом на C# стала в разы быстрей чем была на Си, изза аллокаций памяти неоптимальныъх в Си, а в C# сборщик памяти ускорил дело, представляете (можно было бы использовать как контр-пример что мол круто сборка мусора ускоряет). Но потом ее еще оптимизировали на пулы и она стала быстрей чем была, на всех платформах, т.е. на C# с ручным менеджментом памяти стала быстрей чем на C# со сборкой мусора, и быстрей чем на Си с ручным менеджментом.
Либа эта LibTessDotNet на C# и при желании нагуглите ее версии На Си и С++ и т.п.
А в моем проекте кроме ее я юзаю еще кучу разного.
Если хотя бы новый функционал не писать на С и С++
перепишите мне все используемые мной API с с++ на Rust и я подумаю. Только в моей конторе это тысячи человеколет кода
Если у системы достаточная степень decoupling'а, все в разделяемых библиотеках, или что лучше — коммуникация между модулями по протоколу типа REST, то все же прекрасно переписывается?
Intel mkl: github.com/termoshtt/rust-intel-mkl
Eigen: github.com/GuillaumeGomez/rust-GSL/blob/master/src/eigen.rs
github.com/vberger/dlib — dlib, это оно?
Или вы действительно все статически влинковываете в С++ коды?
https://github.com/GuillaumeGomez/rust-GSL/blob/master/src/eigen.rs
Чё-т не похоже на http://eigen.tuxfamily.org/index.php?title=Main_Page ну вот прямо совсем. Похоже на биндинги к GSL.
github.com/vberger/dlib — dlib, это оно?
Нет, не оно. Оно — это http://dlib.net/ .
Или вы действительно все статически влинковываете в С++ коды?
Увы, с темплейтами иначе никак.
Имелась в виду вот эта библиотека: eigen.tuxfamily.org/index.php?title=Main_Page, которая, как назло, линкуется статически с C++ кодом, ибо header-only на шаблонах :P
Вообще, прям очень любопытно было заодно увидеть биндинги для OpenCV и PCL для Rust'а, вот только это как-то очень долго делать, имхо.
P.S. по вашим ссылкам в части GSL все вызовы плюсовых функций помечены как unsafe. В чем в таком случае будет преимущество использования Rust, если у меня какой-нибудь суровый математический модуль с gpu-оптимизациями? Проще уж тогда к этому моему C++ модулю писать Rust биндинг. Но вызовы модуля мне придется точно так же помечать как unsafe…
P.P.S. Как, кстати, у Rust'а с Cuda/OpenCL?
автор исследовал кодобазы возрастом 10+ лет. Rust вышел в 15-м году, после c++14. Может хватит уже сравнивать Rust 2015 с с++03?
Ну, автор не совсем прав в таком сравнении, но новые версии не сильно улучшают ситуацию. На хабре же была статья про std::visit, там подробно рассказывается про то, почему он не является полноценной заменой нормальному матчингу.
Да, в новых версиях стало все немного лучше. Но можно взять какой-нибудь хромиум, написанный по лучшим гайдлаинам с распоследними плюсами, и все равно там будут ошибки этого класса, причем как мне кажется, их количество от общего количества заведенных багов будет превалирующим.
перепишите мне все используемые мной API с с++ на Rust и я подумаю. Только в моей конторе это тысячи человеколет кода
Так я не говорю переписывать всё с плюсов. Переписывания кода на новый язык «просто потому что» это бездумно и не нужно. Вопрос в том, какие плюсы дает версия на новом языке, и насколько легче написать всё на нем с нуля, чем дописывать существующую версию. Иногда профит есть, и смысл имеется. Иногда — нет. Вопрос в том, чтобы не ударяться в обе крайности.
Ну и да, я обычно пишу на C#, у нас обычно проект — это десятки-сотни отдельных модулей, линкуемых динамически, которые могут быть даже на разных языках, и которые спокойно можно менять/заменять по одному. Ситуация статически линкуемых шаблонов мне действительно чужда, и тут нужно сильно увеличивать стоимость внедрения. И если она превышает некоторый порог — говорить «нет, у нас плюсы. Да, это плохо, но профит от переписывания на раст никогда не окупит затрачиваемые усилия».
и все равно там будут ошибки этого класса
а можете привести пример ошибки памяти в хромиуме, в модуле, написанном на «распоследних» плюсах?
А статическая линковка решает очень много проблем с зависимостями и версионированием библиотек, а также с воспроизводимостью конфигурации. В расте, емнип, именно статическая сборка является вариантом по умолчанию
Системы нынче стали настолько сложные, что даже болванка (заготовка) игры на новомодном движке может весить 200 МБ! Проблема в том, что человечество до этого момента не сталкивалось ни с чем подобным. До этого приходилось управлять максимум небольшими командами либо огромными однотипными системами. Или вообще пускать все на самотек и придерживаться традиций. А цена ошибки не была большой, т.к. часть людей вполне официально можно было считать даже рабами, как в той же Америке до 1865г.
Проходит 150 лет (+3) и системы усложнились на порядки. Ладно бы просто найти решение, но что делать с Legacy/наследием? Раньше решалось проще — повоевали и все, строй заново, без Legacy.
На этом моменте в книгах про известную личность пишут — и тут эта личность создала комитет/общественную организацию/свою книгу/другие варианты. С помощью чего и занимался подобными проблемами.
Может, стоит подумать в направлении такого созидательства? Посмотреть, что уже существует и делать свое, развивать. Типа «общество сложных систем», который позже станет институтом/университетом. На самом деле не взлетит, т.к. нужны будут финансы. Требовать финансирования глупо — можно перейти в режим грантоедов. Поэтому нужно подумать и в сторону о пользе, которую можно получить уже сейчас, пускай и другим путем.
… и это хорошо. У этой библиотеки открытый исходный код, как и у любой библиотеки на Go. Это классно! Вливайтесь! Размер 1мб тем не менее позволяет запуститься в Docker-образе scratch, т.е. с нуля, без всего. А минимальный java-образ весит сотню мегабайт несколько я знаю.
А вот консольная программа того же, да и еще с выключенным дампом откладки дает уже в районе сотни килобайт, причем часть можно сэкономить, если не использовать некоторые системные библиотеки, типа SysUtils.
Почему не пропагандируется Lazarus? Открытый развивающийся язык, куча библиотек. Можно писать даже драйвера. Можно даже GNU Pascal вспомнить.
Хотя уже существует KolibriOS, которая написана на ассемблере. Там нет упора на безопасность, но разработка на ассемблере намекает, что на ассемблере писать можно даже ОС, только не все осилят.
Если без GUI в консоли, то получаем 32КБ. Сравниваем с С-приложениями и как-то порядок особо не различается.
DevCpp х64 для простенького консольного HelloWorld на C++ c iostream дает приложение 1,83Мб
Lazarus 1.8.0 x64 для консольного приложения с расширенными возможностями (включен объект App) дает приложение 278 Кб
FPC 3.1.1 x64: для HelloWorld с библиотеками Classes и SysUtils дает 162 Кб,
без библиотек дает 32 Кб (первая библиотека дает несколько встроенных классов, вторую либу использовал только ради функции перевода из Str в Int и обратно вместо процедуры для того же самого результата).
родные С-приложения с окошками?
Например на WinAPI.
DevCpp х64 для простенького консольного HelloWorld на C++ c iostream дает приложение 1,83Мб
Там же gcc, который тянет свой рантайм.
Например на WinAPI.
и потеря кроссплатформенности.
Опять же — реализовывать можно по-разному. Для Lazarus:
1) не парясь что под капотом. LCL, создавая кнопочки как в Delphi. WinApi, Qt или GTK выбирается переключателем в настройках проекта. Но итоговое приложение будет в районе 2МБ.
2) делая с готовыми обертками на WinAPI, но прирост все равно будет — в районе 300-600КБ, т.к. линкуются библиотеки
3) найдя усеченные библиотеки отрисовки (уже не помню как называется), направлены на минимизацию итогового размера приложения. Итоговое приложение 150-400 Кб
4) Писать все ручками, в том числе обертки для DLL. Можно уложиться до 150 КБ
У меня все цифры примерные и иногда указаны в большую сторону. Например, думал что минимальное консольное приложение 52Кб, а оказалось — всего 32Кб, т.е. я в 1,5 раза завысил.
А еще можно включать опции на дополнительное сжатие, обрезание заголовков, smart-линковку (с перекоспиляцией библиотек, в том числе системной) и т.д., получим еще больше экономии. Еще я использовал х64 компиляцию, а она тоже накладывает свои расходы, так что можно выручить еще пару килобайт.
Доходя до размеров, сопоставимых с размерами дискет в 1,44Мб, я перестаю задумываться о дальнейшем уменьшении размеров минимально компилируемой программы. К сожалению, у многих современных разработчиков эта планка превышает 100Мб и вовсю стремится к гигабайтным высотам.
При сравнимом удобстве написания гуя Qt и Wx дают по ~50/~25 мегабайт (емнип), они включают фреймворк. На Qt ещё и станцевать надо для получения дистрибутива (в бесплатной версии).
На чистом WinAPI не пишу, зачем это в 2к18? Если со скуки, то можно и на FPC написать с вызовами WinAPI, а лучше — на ассемблере.
Или вы знаете некий секретный вариант с Си?
В дебаг сборке еще можно поставить флажок «файл отладки отдельно» и тогда отладочный файл генерируется, но не включается в готовый exe-файл.
Все равно размер будет гулять ± несколько процентов из-за версии Lazarus и ОС, но это уже не так заметно.
Fortran тоже в некоторых применениях просто идеален, оптимизированный и быстрый, но время языка прошло, ровно как и время pascal. Этим языкам даже поддержка корпорации не поможет. Я дорабатывал проект на Delphi, и объективно и непредвзято могу сказать, что он устарел. Я пару раз уже писал об этом на Хабре. А если субъективно, то меня ничто не заставит на нем больше работать, даже, скажем, оффер х2 от текущей денежной компенсации.
Вообще нужно выбирать инструмент исходя из задач. У меня:
— 1С для бухгалтерии
— Python для веб-сервера (ранее использовал PHP)
— C# (Unity) для разработок игр/приложений на телефон
— Lua для скриптов (тут еще Python и Bash, скриптов много)
— Visual Basic for Application для Microsoft Word/Excel/Access
— SQL для баз данных
— JS для клиентских браузерных скриптов
и прочее.
И тут я солидарен с автором статьи, что от С/С++ стоит отказываться во многих направлениях.
А если субъективно, то меня ничто не заставит на С/С++ больше работать, ибо полиформизм инструкций в зависимости от контекста как у тех же звездочек — очень сильно бесит, а про код в стиле регулярок я даже не расписываю. Про указатели упомянуто у автора статьи. И я не собираюсь пихать С/С++ в бухгалтерию, веб-разработку, скрипты, базы данных и т.д.
Я уже не буду рассказывать про рекомендации в сторону NASA выбрать Rust/Swift для разработки, если решение принималось в 90-е! Там вообще клиника.
Например, я хочу организовать иерархические слои данных. Выделяю мегабайт памяти и располагаю там свои любые данные. Выделяю следующий мегабайт и располагаю там новый слой данных, со ссылками на предыдущий слой. И так далее. Следующие слои ссылаются на предыдущие, но не наоборот. Можно удалить N последних слоёв и вся структура останется ссылочно корректной. На расте так не сделаешь.
1_) текущим знанием
2_) легкостью обучения для опытных и для новичков, кривые обучения
3_) з/п специалистов и предложения на биржах труда — влияет на стоимость поддержки
4_) уровень и планируемая длительность поддержки
5) доступность исходного кода
6) лицензии
7) возможности языка
8_) доступные компоненты/библиотеки
9) поддерживаемые целевые ОС и архитектуры
10_) количество изменений в новых версиях языка и влияние на предыдущие
11_) предсказуемость языка, т.е. предсказуемость поведение готовой программы
12) защита от ошибок на уровне языка
13) возможности языка по отстрелу ног и уничтожению всей вселенной
14_) развитость IDE
15_) доступность отладчиков (стандартных для языка, а не сторонних)
16) читабельность
17_) легкость установки от «запустил exe, установил и можно кодить» до «скачай, скомпилируй, исправь ошибки компиляции, скомпилируй более новую версию, настрой конфигурацию, докупи оборудование...»
и т.д.
Например, си допускает в конструкции if присвоение вместо сравнения, а это — частая ошибка, которая отслеживается только некоторыми IDE, в блокнотах можно и пропустить. Про «докупить оборудование» намекнула Unity, которая для создания приложения для Android требует самую новую видеокарту (DirectX 9 уже не устраивает) и х64 систему.
И все языки хоть где-то, но накосячат, т.е. не являются идеальными, поэтому п.1-4, 8, 10, 11, 14, 15, 17 вполне могут быть провалены, особенно новичками п.2,8,14,17
Кроме того, пример Дельфи, Явы, да и впрочем любого приложения со сплеш-скрином «гружусь» показывает, что проблема загрузки никуда не делась.
Много сейчас программ с мгновенным временем запуска <200мс?
Большой файл-долгая линковка, тоже удлиняет цикл разработки.Нет, потому что для си-шной линковки нужно прочитать большой блоб .lib-файл, нарезать его на кусочки, сшить эти кусочки заново в маленький файл, поправив ссылки (не говоря об обязательной для такого действия оптимизации «link-time code generation», когда после сшивания в другом порядке неплохо бы заново код перегенерить). А для го-шной линковки один большой блоб, уже хорошо оптимизированный, сшить с кодом программы и поправить ссылки только в программе на блоб.
1) нужно кучу страниц загрузить в оперативу. Т.е. пока не загрузятся картиночки для отрисовки кастомной кнопочки — приложение будет грузиться.
2) инициализация переменных. Причем всех и сразу, даже в принципе неиспользуемых
3) различные проверки. Вышла новая версия? У пользователя активирована лицензия?
4) Дергать реестр. Либо INI-файлы. Хорошо, если там десяток параметров
5) п.4 расширенный — подгрузить последнюю пользовательскую сессию
6) проверить совместимость системы (встречались и такие программы)
Это некоторые причины. Но программисты не стоят на месте, поэтому ожидайте (а где-то уже появилось):
— телеметрия
— интеграция с другими приложения, которые надо тоже тут же запустить
— 100500 сервисов/микросервисов (у видеокарты NVidia драйвер притащил около десятка программ, в том числе «стримминг», «3д навороты, недоступные на обычном мониторе, но всегда автивные» и прочее.)
— синхронизация с облаком. Если инет затупит, то и приложения тоже замедлится
— высококачественные текстуры 4к для отрисовки курсора мышки
и т.д.
там же и время сборки можно посмотреть.
вроде на хабре было
в то время как проверенные альтернативы, такие как Rust, Swift,
Это шутка такая?
После нескольких лет активной разработки первая стабильная версия (1.0) вышла 15 мая 2015 года (википедия)
Проверенные альтернативы — это «мы целый месяц тестили, все ок». А также намек на то, что до 2014 года у пользователей не должно быть этих самых браузеров, потому как «проверенный временем» язык программирования еще даже не родился
У интернетов могут быть серьезные проблемы из-за языков, подобных английскому или русскому потому, что на них можно нести всякую чушь.
А Rust действительно проверен. Он безопасен по-определению, т.к. все перечисленные проблемы в нем конкретно решены в самом языке. Не имеет никакого значения, сколько он пробыл на рынке.
А Rust действительно проверен. Он безопасен по-определению, т.к. все перечисленные проблемы в нем конкретно решены в самом языке.
Он (сам по себе) не решает более серьезные проблемы — валидации [внешних] данных, не говоря уже про логические ошибки.
К примеру, если (предположим) писать веб-сайты на Rust, он никак не спасёт ни от SQL injection, ни от кучи других проблем имеющих отношение к Web Application Security, равно как и вообще любых проблем которые выходят за рамки безопасных указателей и безопасной работы с памятью.
Ради интереса, пройдитесь по CVE и посчитайте долю уязвимостей связанных с неправильной работы с памятью, и долю всех остальных — результат явно укажет что «безопасный» язык проблему не решит.
не решает более серьезные проблемы — валидации [внешних] данныхНо ведь он навязывает создание типов и трейтов на каждую мелочь. Чужие трейты нельзя реализовать для чужих типов, таким образом, если хотите пользоваться чужим кодом (я имею ввиду, не данные, а зависимости), необходимо создавать свои типы, а это уже намекает на валидацию, хотя и не обязывает, это да.
посчитайте долю уязвимостей связанных с неправильной работы с памятью, и долю всех остальныхА вот Гейнор насчитал более половины.
Даже ядро ОС и то спокойно пишется на полностью безопасном языке, т.к. мизерное количество кода напрямую работает с памятью.
Рискну предположить, что в этом случае ядро будет очень сильно тормозить. Как пример — безопасный язык просто обязан проверять соответствие индекса размерам массива, это несколько лишних операций, больно бьет по кэшу и т.п. — а в ядре ОС таких операций немало, причём в довольно критичных местах.
Ни одна проверка не обходится даром, за это приходится платить либо производительностью, либо памятью, либо и тем и другим — для ядра это очень расточительно.
А для остальных приложенией — да посмотрите на мир Java, типа супер-безопасный язык (с точки зрения указателей как минимум), и сколько уязвимостей уже было в продуктах на нём писанных.
Не поймите неправильно, я не утверждаю что не нужны безопасные языки, или что не нужно жертвовать производительностью ради безопасности — просто проблему нужно решать с другой стороны.
Если законодательно ввести штраф за каждую обнаруженную уязвимость, т.е. ответственность разработчика за качество кода, вот тогда проблемы начнут решаться — код будут вылизывать. В конце концов, почему, если рушится мост или дом, архитектора или строителей могут наказать, а программистов — нет? Уязвимость (и даже банальный баг) в программном продукте также может быть смертельной, или приносит существенные убытки, только вот никто за это не несет никакой ответственности (если и несёт, то в лучшем случае это бьет по репутации, и то ненадолго).
Пока все лицензии на софт (включая коммерческий, и даже критичный, типа ОС) содержат явный отказ от ответственности, или, в лучше случае, «мы вернем вам деньги за покупку», у производителей почти нет никакого стимула делать его свободным от уязвимостей или ошибок.
С другой стороны, возьмём софт который работает в борткомпах каждого современного автомобиля, самолёта etc — часто там обнаруживают уязвимости? А удаленные? Да хотя бы просто баги, такие, которые не позволяют нормально пользоваться техникой — часто? А ведь он чуть меньше чем полностью писан на C, а то и ассемблере. Автомобили сами не тормозят и не ускоряются (только давайте не будем про Tesla & co), не мигают фарами, самолёты не меняют высоту, и т.п. Отдельные фейлы случаются, но это исключительно редкий случай. Дело же просто в том, что как раз баги и уязвимости в таком софте приводят к реальной ответственности — поэтому их там почти нет, по крайней мере не такие какие были бы заметны обычным пользователям.
Так что, повторюсь — язык это дело десятое.
Если законодательно ввести штраф за каждую обнаруженную уязвимость, т.е. ответственность разработчика за качество кода, вот тогда проблемы начнут решаться
… тогда проблемы начнут решаться при помощи счёт и абаков. Потому что софт будет стоить не просто не дорого, а очень дорого. И идти только в виде узкоспециализированной железки. Вот вам отдельный опечатанный ноутбук с вордом, вот вам отдельный опечатанный ноутбук с экселем, ну и да — вот вам dvd плеер для дисков с порнухой.
Да, написание качественного софта стоит денег и времени, но вы посчитайте все убытки связанные с уязвимостями и критичными багами — во многих случаях они явно превышают затраты на разработчиков, которые потребовались бы для написания софта без таких багов, которые приводят к этим самым убыткам.
Лучше опечатанный ноутбук с вордом, но при этом уверенность в том что никакой левый файл, открытый в этом ворде, не сможет натворить делВ чём проблема? Заказывайте себе такой ноутбук с вордом за пару миллиардов долларов, заключайте договор со всеми штрафами и санкциями за ошибки. Но зачем остальным это навязывать?
Вы не купите автомобиль если не будете уверены что его тормозная система тщательно проверяется и работоспособна, а если вдруг в конкретном случае она будет глючить, то производитель будет нести полную ответственность — так почему с программными продуктами должно быть иначе?
так почему с программными продуктами должно быть иначе?Потому что нет платёжеспособного спроса. На надёжные автомобили есть спрос, на надёжные офисные программы — нет.
если кто-то берет деньги за свой продукт, он обязан нести за это ответственность, или, как минимум, заранее огласить весь список возможных проблем.
Он обязан не больше, чем написано в договоре, который вы с ним заключаете добровольно и по обоюдному согласию.
Например, тогда тебя не возьмут на работу или вообще не допустят к клавиатуре, если ты не сдал экзамен и не имеешь сертификата «Уверенный пользователь Word со знанием VBA»…
Это еще не говоря даже про программирование, где программу придется сдавать госкомиссии. За свой счет.
Точно этого хочешь?
то все коммиты в компании начнет совершать «программист» нанятый из дворников, а все люди пишущие код вдруг станут консультантами.
Например, чтобы попользоваться программой, вы будете подписывать договор платного бета-тестирования (ага, сами будете доплачивать за возможность тестирования неготового софта). Обязанность тестировщика — сообщать обо всех найденных ошибках производителю. Не хотите — не участвуйте, но выбора у вас большого не будет.
Хотя проще, вероятно, будет сделать иначе — не берёшь денег — не несёшь ответственности, берёшь — несёшь в полной мере и никак не можешь её исключить в лицензии.
При таком раскладе, компании которые изначально озаботятся качеством, окажутся однозначно в выигрыше — да, их продукция будет стоить дороже, но зато у них будет гарантированный доход. Остальные могут давать свои продукты тестировать бесплатно, пока не вылижут до возможности брать деньги.
Любой пользователь коммерческих программных продуктов должен иметь обеспеченную законом гарантию, причём на уровне покрытия доказуемых понесенных убытков, а не просто «вернём деньги» или «заменим бесплатно» — тогда дело сдвинется с мёртвой точки.
Софт, даже большой и сложный, и даже на C или ассемблере, можно писать без багов, просто весьма ограниченное число компаний (и людей) на это способно и имеет желание, и ещё меньше имеет достаточно денег.
Любой пользователь коммерческих программных продуктов должен иметь обеспеченную законом гарантиюЕсть гарантия, обеспеченная законом, достаточно заключить такой специальный договор. Никто вам не мешает покупать софт на таких условиях.
Когда вы покупаете автомобиль или дом, вы заключаете специальный договор? Сомневаюсь. Но производитель всё равно несет ответственность если откажут тормоза, или если дом рухнет потому что плохо построен или спроектирован.
Да, сейчас у него много донатов, но вначале было не так — тем не менее на качество это не влияло.
Можно и ещё найти примеры, но их можно на пальцах пересчитать, хотя сам факт их наличия (при отсутствии у авторов кучи денег) говорит о том что для качественного кода совсем не нужны миллиарды и сотни лет разработки.
И что теперь, вообще запретить криворуким программировать? Или запретить им выкладывать свои программы на публику? Не много ли вы на себя берёте?
И да, если бы я был законодателем — ввёл бы экзамены на качество кода и лицензию на коммерческое программирование. В конце концов, за руль без прав не пускают, врачебную практику тоже лицензируют, почему тут должно быть иначе?
А для хобби, за бесплатно — пусть себе пишут без лицензии, так уж и быть :)
Кроме того, вы хотите со всех сторон индустрию зажать: компании штрафовать за недоработки их продуктов, программистов экзаменовать, или уже от первой идеи отказались?
В Германии есть хороший пример в этом плане (в других областях), называется Meisterbrief. Это сертификат, выдаваемый профессионалу (с необходимостью доказать свои знания в теории и практики), и дающий ему право на осуществление соответствующей деятельности и открытие фирмы по профилю. Он может нанять «подмастерьев» и вообще кого угодно для выполнения работы, с образованием или без, но отвечать за работу будет лично он. Для ряда профессий наличие этого сертификата является обязательным условием для оказания услуг на коммерческой основе (и даже «просто так» — для врачей и юристов, например).
Эта система, увы, не идеальна и не свободна от недостатков, но сама идея довольно здравая — если кто-то хочет быть врачом, электриком, сантехником, то он обязан доказать свою профпригодность, и должен нести ощутимую ответственность за свои ошибки. При правильном подходе можно исключить (или сильно уменьшить) варианты когда «зубрилы» получают такие лицензии, реально не обладая необходимым опытом или знаниями.
А теперь представьте, что система таки реализована. Вы — владелец лицензии, и вам нужно нанять программистов. Зная, что за их ошибки с вас могут снять либо голову либо много денег, вы примете все меры чтобы они были очень крутыми, либо сами будете перепроверять их работу по десять раз, пока не убедитесь что они не накосячили. Тяжко? Тяжко, зато на выходе будет качественный продукт. Ну или придётся заняться чем-то ещё, чтобы с голоду не умереть.
К сожалению, всё это только теория. На практике скорее ИИ научат писать программы не хуже людей, чем произойдут такие законодательные изменения, а до этого момента будем страдать.
Нужна бухгалтерия? Вот вам услуга — бухгалтер-фрилансер, который будет использовать наш софт и наш хард и никогда на нас не подаст в суд за ошибки в этом софте, потому что он оформлен как соавтор программы. Наёмный бухгалтер будет отвечать за итоговый результат работы (вы ведь ради этого всё затевали), но точно так же и сейчас бухгалтер отвечает за результаты бух. программы, а программисты снова типа не при чём.
Фрилансер-оператор ОС, выполняющий распоряжения пользователя для работы с ней, при этом не могущий подать в суд на разработчика ОС, поскольку является её соавтором — вы примерно так себе это представляете?
С бухгалтерией и похожими вещами я ещё могу представить такую схему, но как быть с ОС, смартфонами, играми, текстовыми редакторами, СУБД, броузерами и IoT?Всё очень просто. Весь мир останется на продуктах больших корпораций, а страна, которая дошла до такого маразма, останется отрезанной от мирового ИТ. В белую будет вынуждена использовать открытое ПО (от ОС до браузеров и офисов) — и тут некому будет предъявить за косяки, т.е. ваша цель не достигнута, а в серую продукты корпораций, естественно тоже без права предъявить претензии.
Либо как вариант контора разрабатывает бесплатный софт (но не открытый), предприятие является безвозмездным спонсором, и пользуется разработанным софтом опять же без претензий.
Во-первых, пряморукие разработчики всё же останутся, и смогут зарабатывать больше, по той простой причине что люди охотнее заплатят за софт зная что есть гарантии (я про ту часть мира где люди всё же привыкли платить за софт, если он платный).
Во-вторых, это стимулирует разработки в области ИИ для автоматизации либо написания программ, либо их качественной проверки на косяки, что приведет к безглючному софту. В крайнем случае, можно сделать качественные песочницы для популярных ОС, дабы минимизировать (или вообще убрать) последствия багов и уязвимостей, так чтобы никакой вирус или троян не смогли ничего сделать без явного разрешения пользователя (прощайте, вымогатели и вирусы).
Так что в долгосрочной переспективе это win-win, хотя может быть и неприятно некоторое время, особенно для криворуких.
Во-вторых, это стимулирует разработки в области ИИ для автоматизации либо написания программ, либо их качественной проверки на косякиАвто-проверка да, улучшится. Но безглючный софт — не значит быстрый и оптимальный. Скорее наоборот, будут перепроверять каждое действие тремя разными алгоритмами, а ошибки тщательно скрывать от пользователя. Сейчас программа упала — core dump и багрепорт. А будут все такие случаи тщательно заметать под ковёр. Данные повреждены? А вы докажите, что это из-за программы, а не пользователь их удалил.
можно сделать качественные песочницы для популярных ОС, дабы минимизировать (или вообще убрать) последствия багов и уязвимостей, так чтобы никакой вирус или троян не смогли ничего сделать без явного разрешения пользователя (прощайте, вымогатели и вирусы)И сейчас можно (белый список EXE и DLL-файлов, разрешённых к загрузке), но никто не делает, т.к. работать неудобно.
а ошибки тщательно скрывать от пользователя
Трудно скрыть воспроизводимые ошибки типа «выполнил ряд действий — программа вылетела», а также уязвимости. В крайнем случае можно это задокументировать в присутствии нотариуса (или другим признаваемым законом способом, включая видеозапись).
Доказать что данные повреждены не пользователем тоже можно, как минимум косвенно, иначе бы Microsoft не признали что их апдейт удаляет данные, а Quora бы заявили что пользователи сами свои данные отдали.
И сейчас можно (белый список EXE и DLL-файлов, разрешённых к загрузке), но никто не делает, т.к. работать неудобно.
Там где критично — делают. Но можно сделать это так чтобы было максимально удобно и незаметно, хотя это и потребует усилий.
Трудно скрыть воспроизводимые ошибки типа «выполнил ряд действий — программа вылетела»В том-то и дело, что «программа вылетела» будут явно запрещать. Это несложно, установив глобальный перехватчик исключений. При этом, проблема может и правда быть незначительной, просто её никто не увидит и не починит.
иначе бы Microsoft не признали что их апдейт удаляет данныеПотому что им выплачивать компенсации не надо, а иначе сказали бы — доказывайте сами, мы против себя не будем свидетельствовать.
Но можно сделать это так чтобы было максимально удобно и незаметно, хотя это и потребует усилий.Это потребует денег, потому что настройкой должен заниматься администратор. А бизнес не хочет платить (в том числе за договоры, гарантирующие финансовую отвественность поставщика ПО), потому везде всё и уязвимо.
При этом, проблема может и правда быть незначительной, просто её никто не увидит и не починит.
Если проблема настолько незначительна, что просто незаметна и не мешает программе выполнять свои функции — то какая же это проблема? Но вот «перехватить» порчу данных из-за неправильной работы с памятью (или алгоритма обработки) ой как непросто — данные таки будут испорчены, и скрыть это будет трудно. Равно как и «перехватить» уязвимость с проникновением — тоже практически нереально, она либо есть либо нет (и доказуема легко, если обнаружена).
Если проблема настолько незначительна, что просто незаметна и не мешает программе выполнять свои функции — то какая же это проблема?Это не проблема, если бы не ваши предлагаемые драконовские меры. Например, при закрытии окна выкидывается исключение, потому что какой-то ресурс освобождается дважды. Вы же — «ага, попался подлый капиталист, теперь заплатишь штраф за глюки». А погасил все ошибки, и проблемы якобы нет, и никто её не решает.
Но вот «перехватить» порчу данных из-за неправильной работы с памятью
Google sanitizers(AddressSanitizer, ThreadSanitizer, MemorySanitizer), Intel MPX, The Application Verifier всякого рода туллинга завались
И первая же ошибка уровня heartbleed пустит их по миру, а остальных заставит заранее уехать туда, где нет подобных гениальных идей.
> ИИ для автоматизации либо написания программ
Будут как ясновидящие в разведке — добывают сведения старым проверенным способом, а этих выставляют как ширму. «Мы не отвечать, эта программа ИИ написать, не наш программист, у нас и нет такой».
> Трудно скрыть воспроизводимые ошибки типа «выполнил ряд действий — программа вылетела», а также уязвимости.
Программа не будет вылетать, будет песочница в песочнице в песочнице. И работать будет в разы медленнее. Если что-то падает — возвращаемся ко входу в программу и говорим что «система подозревает что пользователь не тот и требует повторного логина, это требование безопасности». Что при этом не сохранились данные, так пользователь сам виноват и чинить не будут.
Уязвимости? А в чём выражаются? Данные утекли, а как это доказать? Может, пользователь продал. Или не будет обмена через сеть. Надо обменяться — печатай и вбивай руками, зато уязвимости нет.
> иначе бы Microsoft не признали что их апдейт удаляет данные, а Quora бы заявили что пользователи сами свои данные отдали.
Вы же сами сетуете что им за это ничего не было, а даже сейчас есть скрывающие до последнего утечки, тогда давайте штрафовать комании за утечки по вине персонала, чтобы добить окончательно.
Тем более компьютеров у пользователей рядовых и не будет — не смогут себе позволить столь дорогое удовольствие, а если и будут, то несовместимые с корпоративными (на текущих ОС и софте, в отличии от проверенных систем, которые не должны тащить ошибки прошлого, а совместимость — уже не конкурентное преимущество). Это сейчас софт берёт массовостью, деля цену на всех, а в вашем случае производитель будет не заинтересован в массовости (больше вариантов иска), но заинтересован в прежней выручке (и даже большей), потому цена вырастет кратно.
Зачем вам ОС? У бухгалтера она есть, а вам не надо, вам надо будет снова становиться законодателем, чтобы обязать бухгалтера не сливать ваши данные (а то вы снова понадеялись законодательство и не включили эти пункты в договор).
Смартфон не нужен, есть домашний телефон как услуга, есть таксофон, смартфон — пережиток прошлого, дикой эпохи ненадёжного софта. Как и эти ваши гадкие автомобили, в которых тоже был софт. Пользователь доехал на лошади до таксофона и звонит. Текстовый редактор тоже бесовское изобретение, достаточно дойти до бюро машинисток, которые предоставляют соответствующие услуги.
> вы примерно так себе это представляете?
И ещё немного подпольного софта, который не требует гарантий и можно использовать на свой страх и риск, зато не платя миллионы.
Я склонен считать, что с лицензиями на ПО всё было бы сильно хуже. И от лицензий на мостостроительство, кстати, это существенным образом отличается, ибо конкуренцию мостов устроить чуть сложнее, чем ПО.
Результат вас, скорее всего, удивит.
И получат конкурентное преимущество над теми, кто не подпишет и останется со счётами и логарифмической линейкой.
Можете попробовать начать с себя — заказать для своей деятельности софт (начиная с ОС, хотя лучше начать с прошивки железа, а ещё лучше с самого железа).
Вам не кажется очевидным, что к вам выстроится очередь желающих продать свои услуги?
> Посмотрите на sqlite — он вообще public domain, фичи регулярно добавляются, баги фиксятся, да и код вылизан покруче чем у большинства.
Вылизан исключительно потому что его авторы зарабатывают где-то ещё, если им не на что будет жить, то он будет вылизан исключительно в попытках найти на повехности что-то съедобное.
Как пример — безопасный язык просто обязан проверять соответствие индекса размерам массива, это несколько лишних операций, больно бьет по кэшу и т.п. — а в ядре ОС таких операций немало, причём в довольно критичных местах.
Не обязан, можно делать это статически, а в рантайм вынести в среднем не более одной проверки перед циклом.
Как раз в соседнем треде завтипы обсуждаем.
weird(int[] arr)
{
for (int n = 0; n < arr.length; n++) {
arr[arr[n] ^ 0x55] ^= 0xAA;
}
}
И как можно статически это проверить? А если условие не имеет отношения к индексу и/или размеру, и индексы вычисляются извне, то в начале цикла вообще нет смысла проверять. Пример конечно искусственный, но это чисто для демонстрации.
Поэтому в «безопасном» языке либо придётся «дуть на воду», либо явно отключать такие проверки прагмами или чем-то ещё (тоже тот ещё способ) — в конце концов, кто-то кто вызывает weird() может гарантировать что никакой элемент не будет больше чем 0xFF и что размер массива как минимум 256 элементов, а вот компилятор этого может и не узнать.
в конце концов, кто-то кто вызывает weird() может гарантировать что никакой элемент не будет больше чем 0xFF и что размер массива как минимум 256 элементов, а вот компилятор этого может и не узнать
Действительно, отличный пример!
Тайпчекер вполне может про это знать, если эта функция ещё и принимает доказательство, что длина массива больше 255, а каждый элемент меньше 256. А откуда эти доказательства возьмутся — дело вызывающего кода. Может, массив по построению такой, и ничего проверять не надо, а, может, просто один раз валидацию каких-нибудь входных данных сделали, и всё.
это величайшее упущение для «безопасного» языка
Безопасный язык по-умолчанию будет дуть на воду. В Rust вы можете реализовать pre/post-conditions через 2 функции, где одна будет unsafe и использовать индексирование без проверки размера, а вторая будет проверять условия и вызывать unsafe функцию.
Тайпчекер и контракты хороши, если весь исходный код доступен и написан на одном языке, компилятору с которого можно всё рассказать.
Так мы ж обсуждаем всё в предположении гомогенности кода, разве нет?
Но в приведённом мной примере Rust не помощник.
А я и не про Rust. Впрочем, и не про контракты, контракты не являются заменой зависимым типам с точки зрения выражения и проверок корректности.
Рискну предположить, что в этом случае ядро будет очень сильно тормозить. Как пример — безопасный язык просто обязан проверять соответствие индекса размерам массива, это несколько лишних операций, больно бьет по кэшу и т.п. — а в ядре ОС таких операций немало, причём в довольно критичных местах.
Без бенчмарков это вилами на воде писано. Да, в чем-то мы проигрываем, а в чем-то выигрываем: например, раст все ссылки помечает как noalias. Какую выгоду это несет по производительности, думаю, говорить не стоит. Или когда можно безопасно ссылаться на данные там, где в вы будете их копировать просто ради собственного спокойствия (пример). Ну и так далее… Или вот статья — как думаете, во сколько раз наивный написанный в лоб раст медленнее оптимизированных плюсов? Ответ думаю вас удивит.
А для остальных приложенией — да посмотрите на мир Java, типа супер-безопасный язык (с точки зрения указателей как минимум), и сколько уязвимостей уже было в продуктах на нём писанных.
И ни в одном из них нет багов use after free и им подобным. Выше уже сказали — если нет техники, избавляющейся от всех проблем, давайте вообще никаких не решать?
Не поймите неправильно, я не утверждаю что не нужны безопасные языки, или что не нужно жертвовать производительностью ради безопасности — просто проблему нужно решать с другой стороны.
Вот в этом ваша ошибка :) Вы думаете, что безопасность и скорость — это взаимообратные величины, между которых нужно балансировать. А если посмотреть на слоган того же раста: Rust is a systems programming language focused on three goals: safety, speed, and concurrency.. И это не маркетинговый буллшит, а действительно так и есть, стоит только посмотреть на примеры которые я дал чуть выше.
Если законодательно ввести штраф за каждую обнаруженную уязвимость, т.е. ответственность разработчика за качество кода, вот тогда проблемы начнут решаться — код будут вылизывать.
Да ладно вам, лучше проще — законодательно запретить (с угрозой расстрела) программистам баги делать. И тогда точно заживем.
С другой стороны, возьмём софт который работает в борткомпах каждого современного автомобиля, самолёта etc — часто там обнаруживают уязвимости? А удаленные?
Постоянно находят. Сколько роликов про удаленный взлом каких-нибудь Тесл не перечислить. И это с учетом тех сил, которые тратятся.
Так что, повторюсь — язык это дело десятое.
Первостепенное. Нужно просто перестать себя обманывать, что «ну мне тут нужно быстро, так что безопасно не выйдет». Нет такой аксиомы :) Это как пятая аксиома Евклида — все к ней привыкли, но на самом деле от неё спокойно можно отказаться.
Или вот статья — как думаете, во сколько раз наивный написанный в лоб раст медленнее оптимизированных плюсов?
Код коду рознь, а если у компиляторов один бэкэнд (LLVM) — то всё опять таки упрётся в дополнительные телодвижения (типа проверки индексов), которые оптимизацией невозможно убрать в ряде случаев, просто в принципе невозможно (см. мой пример выше).
Сколько роликов про удаленный взлом каких-нибудь Тесл не перечислить.
Пример не совсем корректен — Тесла это сырой продукт, да и если докажут что авария случилась из-за взлома, то отвечать будут по полной, «ой извините, баг» не прокатит (ибо регулируемая отрасль).
Речь шла про технику которая работает автономно и недоступна по интернету. Вам же наверняка известно, что почти в любом обычном (современном) автомобиле есть куча микроконтроллеров? А теперь расскажите как часто у вас отключается ABS сама по себе из-за багов. Ну а если отключится — то производитель будет отвечать очень даже материально. Мне лично неизвестен ни один случай, когда пришлось массово отзывать или перепрошивать серию машин из-за бага в firmware, а вам?
Поэтому я и предлагаю ввести ответственность за продукцию, если за это берут деньги — потому что сейчас от этого зависит жизнь, здоровье, благосостояние и т.п. Берешь деньги — давай гарантию, это честно. Накосячил так что потребитель пострадал — отвечай. В чём я неправ?
это не маркетинговый буллшит, а действительно так и есть, стоит только посмотреть на примеры которые я дал чуть выше.
Извините, но это именно маркетинговый буллшит. Толку с того на чём он focused, если писать будет криворукий программист? Ну не сможет он накосячить с памятью, зато накосячит в куче других мест. Даже хуже — криворукий подумает что ему вообще ни о чём думать не нужно, достаточно писать на этом языке (да, многие так думают) — и такого напишет… А для пользователя совершенно неважно как именно он накосячил — важно что «не работает как надо».
Все, абсолютно все без исключения баги (связанные с памятью или нет) — либо от криворукости, либо от невнимательности, либо от усталости, в общем как ни крутите — это вина разработчика (софта или железа), а не языка, так почему бы их не построить, или не контролировать и обучать жёстко?
Моё решение (либо исключить либо жётско контролировать человеческий фактор) универсально, а супер-мега-безопасный язык только создаст иллюзию решения проблемы, хотя решит всего лишь малую её часть.
Код коду рознь, а если у компиляторов один бэкэнд (LLVM) — то всё опять таки упрётся в дополнительные телодвижения (типа проверки индексов), которые оптимизацией невозможно убрать в ряде случаев, просто в принципе невозможно (см. мой пример выше).
Непонятное какое-то сравнение. У хаскелля тоже есть llvm бэкенд, значит ли это, что они будут по производительности равны (если мы уберем проверки индексов)?
Речь шла про технику которая работает автономно и недоступна по интернету. Вам же наверняка известно, что почти в любом обычном (современном) автомобиле есть куча микроконтроллеров? А теперь расскажите как часто у вас отключается ABS сама по себе из-за багов. Ну а если отключится — то производитель будет отвечать очень даже материально. Мне лично неизвестен ни один случай, когда пришлось массово отзывать или перепрошивать серию машин из-за бага в firmware, а вам?
Большинство бытовой и подобной техники — это всякие жабы со всеми вытекающими. Миллиард устройств не на ровном месте взялся.
Извините, но это именно маркетинговый буллшит. Толку с того на чём он focused, если писать будет криворукий программист? Ну не сможет он накосячить с памятью, зато накосячит в куче других мест.
Куча других мест намного более очевидна. Косяки в бизнес-логике можно отловить тестами, например. Хотя вот это отдельно хотел прокомментировать:
Даже хуже — криворукий подумает что ему вообще ни о чём думать не нужно, достаточно писать на этом языке (да, многие так думают) — и такого напишет… А для пользователя совершенно неважно как именно он накосячил — важно что «не работает как надо».
То есть язык должен был максимально неудобным, чтобы программист всегда был «в тонусе»? :)
Все, абсолютно все без исключения баги (связанные с памятью или нет) — либо от криворукости, либо от невнимательности, либо от усталости, в общем как ни крутите — это вина разработчика (софта или железа), а не языка, так почему бы их не построить, или не контролировать и обучать жёстко?
Глупо обвинять в том, что естественно. Примерно как обвинять кондитера, что у него не все пирожки идеальной одинаковой формы.
Моё решение (либо исключить либо жётско контролировать человеческий фактор) универсально, а супер-мега-безопасный язык только создаст иллюзию решения проблемы, хотя решит всего лишь малую её часть.
У вас нет никакого решения. Никто не будет работать по таким правилам вообще. Если вы введете расстрел за баги — наследующий день у вас будет куча новых шоферов и грузчиков, и ни одного программиста.
Непонятное какое-то сравнение. У хаскелля тоже есть llvm бэкенд, значит ли это, что они будут по производительности равны (если мы уберем проверки индексов)?
Одинаковые алгоритмы с одинаковыми структурами данных — да, будут равны. Например, простая функция которая возвращает сумму элементов целочисленного массива — написанная на Rust, C, C++ и хаскеле, пропущенная через LLVM — выдаст (с вероятностью 99,9%) одинаковый код. Если мы углубимся в объекты и тонкости их реализации с таблицами методов и прочими безобразиями — тут уже, скорее всего, будут отличия поболее.
Большинство бытовой и подобной техники — это всякие жабы со всеми вытекающими. Миллиард устройств не на ровном месте взялся.
Я вообще-то говорил не о простой «бытовой» технике, не зря сказал про автомобили — там практически нет багов в продакшн именно потому что производитель очень материально отвечает за их последствия. Насчёт жабы там сильно сомневаюсь, мощности и память не те. Впрочем, думаю, если найдут баг в микроволновке, которая взорвется или загорится из-за перегрузки, если в определенной последовательнсти нажать какие-то кнопки — то призводитель тоже ответит по самое не могу. А если розетка управляемая Алексой не включится — то да, никто не будет отвечать, хотя хз какие там будут последствия.
То есть язык должен был максимально неудобным, чтобы программист всегда был «в тонусе»? :)
Я где-то сказал «неудобным»? Он просто не должен вставать у меня на пути, если я явно этого не хочу. Моя программа — я царь горы. Это инструмент. Если мне непосчастливится работать в компании где это обязательно (стреляющий за ляпы компилятор) — ок, другое дело. Но пока у меня есть выбор — я хочу им пользоваться.
Верьте или нет, но после первых 5 лет написания проектов на C, я научился не делать ошибок связанных с работой с памятью, валидация всего на входе, выходе и даже между ними у меня уже в крови, даже в наскоро написанных программах — зная о чём нужно думать, их легко избегать, особенно когда отладчик использовать невозможно и приходится всё держать в голове (да, в те далекие времена отладчики были роскошью, впрочем, как и наличие какого-либо компилятора C).
И чем мне тут помог бы Rust? Вы конечно скажете что я могу устать, опечататься etc — да, когда-нибудь это начнёт случаться. Но я глубоко уверен, что если человек начинает настолько уставать или становится невнимательным, что делает ошибки в коде (которые не замечает после первого перечитывания на свежую голову) — ему пора менять род деятельности, на тот где он не сможет делать ошибок, по крайней мере таких ошибок которые не сможет исправить до выкатывания продукции в прод.
Глупо обвинять в том, что естественно.
Я не обвиняю, я указываю на источник проблемы. Как это ни прискорбно, но это из серии «нет человека — нет проблем». Поэтому идеальное решение — устранить из цепочки человека. Чуть менее идеальное — заставить его ошибаться почти никогда, или исключительно редко. Получается ведь у тех кто бомбы обезвреживает, почему не получится у программистов?
Никто не будет работать по таким правилам вообще. Если вы введете расстрел за баги — наследующий день у вас будет куча новых шоферов и грузчиков, и ни одного программиста.
Давайте всё же не будем утрировать — я не такие драконовские меры предлагаю. А насчёт «никто не будет» — снова напомню про производителей автомобилей и прочей техники, где ответственность за баги весьма чувствительна (станки с ЧПУ и прочие промышленные роботы, как пример) — работают же, причём почти без багов. По крайней мере без таких которые явно ощутимы или даже хотя бы заметны. Причём, заметьте, автомобили при этом стоят вовсе не миллионы — эти микроконтроллеры и прочие embedded есть даже в дешевых авто.
Не хотите отвечать за содеянное — не берите деньги, а если уж берёте — то отрабатывайте и отвечайте за косяки. Я лично готов, а вы?
Ребята, сворачиваемся.
Например, простая функция которая возвращает сумму элементов целочисленного массива — написанная на Rust, C, C++ и хаскеле, пропущенная через LLVM — выдаст (с вероятностью 99,9%) одинаковый код.
Лол, нет. Я только что собрал тестовый проект с одной функцией, делающей ровно то же:
import qualified Data.Vector as V
sumOverVect :: V.Vector Int -> Int
sumOverVect = foldl (+) 0
с -fllvm и получил
@Main_sumOverVect1_info = alias i8, bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_sumOverVect1_info$def to i8*)
define ghccc void @Main_sumOverVect1_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 4294967301, i64 0, i64 14}>
{
c7tj:
%R1_Var = alloca i64, i32 1
store i64 %R1_Arg, i64* %R1_Var
%Sp_Var = alloca i64*, i32 1
store i64* %Sp_Arg, i64** %Sp_Var
%R2_Var = alloca i64, i32 1
store i64 %R2_Arg, i64* %R2_Var
%ln7u5 = load i64*, i64** %Sp_Var
%ln7u6 = getelementptr inbounds i64, i64* %ln7u5, i32 -7
%ln7u7 = ptrtoint i64* %ln7u6 to i64
%ln7u8 = icmp ult i64 %ln7u7, %SpLim_Arg
%ln7ua = call ccc i1 (i1, i1) @llvm.expect.i1( i1 %ln7u8, i1 0 )
br i1 %ln7ua, label %c7tk, label %c7tl
c7tl:
%ln7uc = ptrtoint void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @c7tg_info$def to i64
%ln7ub = load i64*, i64** %Sp_Var
%ln7ud = getelementptr inbounds i64, i64* %ln7ub, i32 -1
store i64 %ln7uc, i64* %ln7ud, !tbaa !2
%ln7ue = load i64, i64* %R2_Var
store i64 %ln7ue, i64* %R1_Var
%ln7uf = load i64*, i64** %Sp_Var
%ln7ug = getelementptr inbounds i64, i64* %ln7uf, i32 -1
%ln7uh = ptrtoint i64* %ln7ug to i64
%ln7ui = inttoptr i64 %ln7uh to i64*
store i64* %ln7ui, i64** %Sp_Var
%ln7uj = load i64, i64* %R1_Var
%ln7uk = and i64 %ln7uj, 7
%ln7ul = icmp ne i64 %ln7uk, 0
br i1 %ln7ul, label %u7u1, label %c7th
c7th:
%ln7un = load i64, i64* %R1_Var
%ln7uo = inttoptr i64 %ln7un to i64*
%ln7up = load i64, i64* %ln7uo, !tbaa !4
%ln7uq = inttoptr i64 %ln7up to void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)*
%ln7ur = load i64*, i64** %Sp_Var
%ln7us = load i64, i64* %R1_Var
tail call ghccc void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64) %ln7uq( i64* %Base_Arg, i64* %ln7ur, i64* %Hp_Arg, i64 %ln7us, i64 undef, i64 undef, i64 undef, i64 undef, i64 undef, i64 %SpLim_Arg ) nounwind
ret void
u7u1:
%ln7ut = bitcast void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @c7tg_info$def to void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)*
%ln7uu = load i64*, i64** %Sp_Var
%ln7uv = load i64, i64* %R1_Var
tail call ghccc void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64) %ln7ut( i64* %Base_Arg, i64* %ln7uu, i64* %Hp_Arg, i64 %ln7uv, i64 undef, i64 undef, i64 undef, i64 undef, i64 undef, i64 %SpLim_Arg ) nounwind
ret void
c7tk:
%ln7uw = load i64, i64* %R2_Var
store i64 %ln7uw, i64* %R2_Var
%ln7ux = ptrtoint %Main_sumOverVect1_closure_struct* @Main_sumOverVect1_closure$def to i64
store i64 %ln7ux, i64* %R1_Var
%ln7uy = getelementptr inbounds i64, i64* %Base_Arg, i32 -1
%ln7uz = bitcast i64* %ln7uy to i64*
%ln7uA = load i64, i64* %ln7uz, !tbaa !5
%ln7uB = inttoptr i64 %ln7uA to void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)*
%ln7uC = load i64*, i64** %Sp_Var
%ln7uD = load i64, i64* %R1_Var
%ln7uE = load i64, i64* %R2_Var
tail call ghccc void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64) %ln7uB( i64* %Base_Arg, i64* %ln7uC, i64* %Hp_Arg, i64 %ln7uD, i64 %ln7uE, i64 undef, i64 undef, i64 undef, i64 undef, i64 %SpLim_Arg ) nounwind
ret void
}
declare ccc i1 @llvm.expect.i1(i1, i1)
Я это даже не особо пытался прочесть, так что, может, какие-то ещё функции, на которые оно ссылается, я скопировать забыл, но понятно, что для других языков оно будет попроще.
Не, на хаскеле можно писать очень эффективный код, но это не совсем тривиально.
Зато компилятор умный и если заменить foldl (+) 0
на sum
, то он выдаёт точно такой же код, хотя семантика этих двух операций несколько различается с точки зрения строгости.
Хотя если вместо Data.Vector
взять Data.Vector.Unboxed
, в котором все значения уже вычислены, и вычислять ещё раз их не надо, то будет
@Main_sumOverVect1_info = alias i8, bitcast (void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @Main_sumOverVect1_info$def to i8*)
define ghccc void @Main_sumOverVect1_info$def(i64* noalias nocapture %Base_Arg, i64* noalias nocapture %Sp_Arg, i64* noalias nocapture %Hp_Arg, i64 %R1_Arg, i64 %R2_Arg, i64 %R3_Arg, i64 %R4_Arg, i64 %R5_Arg, i64 %R6_Arg, i64 %SpLim_Arg) align 8 nounwind prefix <{i64, i64, i64}><{i64 4294967301, i64 0, i64 14}>
{
c8tk:
%R1_Var = alloca i64, i32 1
store i64 %R1_Arg, i64* %R1_Var
%Sp_Var = alloca i64*, i32 1
store i64* %Sp_Arg, i64** %Sp_Var
%R2_Var = alloca i64, i32 1
store i64 %R2_Arg, i64* %R2_Var
%ln8u1 = load i64*, i64** %Sp_Var
%ln8u2 = getelementptr inbounds i64, i64* %ln8u1, i32 -7
%ln8u3 = ptrtoint i64* %ln8u2 to i64
%ln8u4 = icmp ult i64 %ln8u3, %SpLim_Arg
%ln8u6 = call ccc i1 (i1, i1) @llvm.expect.i1( i1 %ln8u4, i1 0 )
br i1 %ln8u6, label %c8tl, label %c8tm
c8tm:
%ln8u8 = ptrtoint void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)* @c8ti_info$def to i64
%ln8u7 = load i64*, i64** %Sp_Var
%ln8u9 = getelementptr inbounds i64, i64* %ln8u7, i32 -1
store i64 %ln8u8, i64* %ln8u9, !tbaa !2
%ln8ua = load i64, i64* %R2_Var
store i64 %ln8ua, i64* %R1_Var
%ln8ub = load i64*, i64** %Sp_Var
%ln8uc = getelementptr inbounds i64, i64* %ln8ub, i32 -1
%ln8ud = ptrtoint i64* %ln8uc to i64
%ln8ue = inttoptr i64 %ln8ud to i64*
store i64* %ln8ue, i64** %Sp_Var
%ln8uf = bitcast i8* @stg_ap_0_fast to void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)*
%ln8ug = load i64*, i64** %Sp_Var
%ln8uh = load i64, i64* %R1_Var
tail call ghccc void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64) %ln8uf( i64* %Base_Arg, i64* %ln8ug, i64* %Hp_Arg, i64 %ln8uh, i64 undef, i64 undef, i64 undef, i64 undef, i64 undef, i64 %SpLim_Arg ) nounwind
ret void
c8tl:
%ln8ui = load i64, i64* %R2_Var
store i64 %ln8ui, i64* %R2_Var
%ln8uj = ptrtoint %Main_sumOverVect1_closure_struct* @Main_sumOverVect1_closure$def to i64
store i64 %ln8uj, i64* %R1_Var
%ln8uk = getelementptr inbounds i64, i64* %Base_Arg, i32 -1
%ln8ul = bitcast i64* %ln8uk to i64*
%ln8um = load i64, i64* %ln8ul, !tbaa !5
%ln8un = inttoptr i64 %ln8um to void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64)*
%ln8uo = load i64*, i64** %Sp_Var
%ln8up = load i64, i64* %R1_Var
%ln8uq = load i64, i64* %R2_Var
tail call ghccc void (i64*, i64*, i64*, i64, i64, i64, i64, i64, i64, i64) %ln8un( i64* %Base_Arg, i64* %ln8uo, i64* %Hp_Arg, i64 %ln8up, i64 %ln8uq, i64 undef, i64 undef, i64 undef, i64 undef, i64 %SpLim_Arg ) nounwind
ret void
}
А рядом вижу небезопасные инструкции, за счет которых получаем высокую скорость и низкие накладки по ресурсам
За это тоже надо было бить по рукам. К тому же с большой долей вероятности в этом не было никакого смысла, т.к. бенчмарки никто не проводил как обычно это бывает.
Таки Rust практически равен С/С++ в производительности. Ничего бы с интернетом не случилось, если бы внезапно весь стек его технологий был перенесен на Rust. Стало бы только лучше и знаменитый heartbleed мы бы не увидели.
бенчмарки никто не проводил как обычно это бывает.А вот по себе судить не надо, пожалуйста.
Таки Rust практически равен С/С++ в производительности.То есть все таки проводите бенчмарки?
если бы внезапно весь стек его технологий был перенесен на Rust.Внезапно этого точно не случилось бы, как минимум на это нужно потратить много времени. А кроме Mozilla в этом никто особо не заинтересован, насколько я понимаю.
Естественно, существуют различия. Например, в расте нельзя обработать out of memory и поэтому компилятор может агрессивно оптимизировать выделения/освобождения памяти. С другой стороны, исключения в с++ производительнее для преимущественно позитивных сценариев. High ground c++ только в том, что в нем всегда можно повторить поведение «как в rust», а наоборот — нет. Но это почти никогда и не нужно
бекенд у компилятора раста тот же llvm, что и в clang для c++, поэтому разница в производительности эквивалентных программ как правило будет несущественной
Бекендом оно не ограничивается, увы. А то так-то и у ghc есть llvm-бекенд, который, конечно, ускоряет числодробильные задачи, но до максимально оптимизированного кода на плюсах зачастую далеко.
Внезапно этого точно не случилось бы, как минимум на это нужно потратить много времени. А кроме Mozilla в этом никто особо не заинтересован, насколько я понимаю.
В этом и проблема. Людям лень переписывать, а мир таки от этого лучше бы стал. Производительно бы осталась той же, зато испарились бы баги с многопоточностью и уязвимости из-за работы с памятью.
Людям лень переписывать, а мир таки от этого лучше бы стал.
Переписывать с C/C++ на то что кардинально от него отличается по своим концепциям — это огромный труд.
Что мешало взять D в качестве безопасного языка, в крайнем случае допилить его если чего-то не хватает? Уж всяко проще было бы для любого сишника переписать на D, чем учить Rust и его зубодробительные отличия, при этом не имея возможности хотя бы частично использовать имеющийся код.
А как D спасает от рейсов?
Формально доказано, что Rust спасает от всех рейс кондишнов.
Читаем https://people.mpi-sws.org/~dreyer/papers/rustbelt/paper.pdf
Сам по себе язык вполне допускает race conditions (их невозможно проверить статически, особенно если поведение программы в целом и потоков в частности зависит от внешних данных), да и документация не делает таких утверждений, даже наоборот:
So it's perfectly «fine» for a Safe Rust program to get deadlocked or do something nonsensical with incorrect synchronization. Obviously such a program isn't very good, but Rust can only hold your hand so far. Still, a race condition can't violate memory safety in a Rust program on its own. Only in conjunction with some other unsafe code can a race condition actually violate memory safety.
Грубо говоря, пока там есть unsafe код, то никаких гарантий нет и не может быть, не говоря уже о том что race conditions не ограничиваются некорректной синхронизацией обращения к памяти (а только от этого язык и спасает, по сути, и то если не использовать unsafe).
Формально доказано не совсем это, вы хотя бы просмотрите сей труд, что-ли.
А что там доказано?
Грубо говоря, пока там есть unsafe код, то никаких гарантий нет и не может быть
Грубо говоря, вы не правы. Пусть у нас есть безопасный код, разбавьте код unsafe {NOP}
, он будет таким же безопасным.
Вы плохо понимаете смысл unsafe. Советую почитать https://doc.rust-lang.org/nomicon/safe-unsafe-meaning.html
А что там доказано?
Там доказано, что в случае если мы будем использовать сферического коня в вакууме, то race не будет. Конечно, я утрирую, но они делают массу предположений о среде, библиотеках, etc. — а вы пишете «спасает от всех рейс кондишнов» — в то время как в труде говорится о конкретных, а не всех.
Грубо говоря, вы не правы. Пусть у нас есть безопасный код, разбавьте код unsafe {NOP}, он будет таким же безопасным.
Мне казалось очевидным, что речь шла не про unsafe {NOP}. Речь шла о том что при желании, незнании (или неправильном знании, или малом опыте) race очень легко можно устроить, язык этого не предотвратит сам по себе.
Вот если бы ни при каких условиях, независимо от того как и какой пишется код, race были бы невозможны в принципе — тогда да, я бы с вами согласился. Но это, увы, не так.
Заранее отвечая на вопрос, что unafe будет очень много и всех не отследить: в одном известном фреймворке actix была проблема с unsafe, был целый пост на реддите. Автор ни в чем себя не сдерживал, и в большом асинхронном актор фреймворке было аж 100 использований. Но с тех пор была проведена работа, и примерно за неделю количество их было сокращено до 15, каждый из которых был просмотрен десятками глаз, и было решено, что они не UB.
Как сделать подобное ревью любой приличной С++ базы, я не представляю. Смысл как раз в том, что в расте вы грепаете unsafe, и смотрите, нарушаются инварианты или нет. Вам не нужно смотреть миллионы строк кода, достаточно пары десятков строк на каждый unasfe, которых в проекте тоже не больше пары десятков. Это задача, которую можно решить за пару дней. Для довольно крупного проекта.
Попробуйте теперь вровалидировать какую-нибудь akka.net, что в ней нет рейсов. Это я уж про плюсы я молчу.
Хотя, в любом большом проекте с сотнями тысяч строк кода, не зная архитектуры приложения, не зная намерений разработчиков, не зная самого кода (внешний review) греп вам очень мало поможет.
Что касается других языков (любых) — нужно изначально писать код, который к ним не может привести. Пряморукий и опытный разработчик это сделает легко даже на ассемблере, причём на автомате, ему не нужна помощь компилятора.
Я не спорю что языки типа Rust снижают количество очевидных ошибок, но всё равно, большей частью речь только об ошибках связанных с обращением к памятью, в редких случаях других очевидных ляпах (типа присваивание вместо сравнения как в C, хотя это может быть и намеренно) — но это не решает проблему с багами в целом, это лишь уменьшит их количество (ненамного — C/C++ и прочие «небезопасные» языки и так мало где используются уже).
Если даже «прям щаз» всё что написано на C/C++ перепишут на Rust, это не сократит количество багов и уязвимостей даже на половину — по крайней мере, до тех пор пока разработчики не станут намного более квалифицированными.
В этом, собственно, и заключается моя мысль.
Просто память защищена по дефолту. Другие ресурсы нужно самому.
Ещё раз повторюсь — Rust гарантирует только отсутсвие race, связанных с памятью. Точка. Все остальные вы ничем не грепнете, потому что к unsafe они не имеют отношения.
А какие еще race раст должен предотвращать? Конечно же, под памятью мы понимаем любые ресурсы, каналы там, сокеты, и всё-всё остальное. Программа вроде ничего другого и не умеет делать :)
Хотя, в любом большом проекте с сотнями тысяч строк кода, не зная архитектуры приложения, не зная намерений разработчиков, не зная самого кода (внешний review) греп вам очень мало поможет.
Ну вот практика показывает, что вполне поможет. Открываете любой проект, который видите первый раз в жизни. Грепаете ансейф. После этого смотрите на правила раста
Unlike C, Undefined Behavior is pretty limited in scope in Rust. All the core language cares about is preventing the following things:
— Dereferencing null or dangling pointers
— Reading uninitialized memory
— Breaking the pointer aliasing rules
— Producing invalid primitive values:
— — dangling/null references
— — a bool that isn't 0 or 1
— — an undefined enum discriminant
— — a char outside the ranges [0x0, 0xD7FF] and [0xE000, 0x10FFFF]
— — A non-utf8 str
— Unwinding into another language
— Causing a data race
That's it. That's all the causes of Undefined Behavior baked into Rust.
Если определяете любой из этих случаев — UB есть. Если нет — то нет.
Никакой контекст для этого вам не нужен. Т.к. в unsafe не бывает больше десятка-другого строчек, то и понимание проекта вам не особо нужно: достаточно локального понимания, что вот эти переменные таких вот типов, и мы не разыменоваываем null до проверки.
Что касается других языков (любых) — нужно изначально писать код, который к ним не может привести. Пряморукий и опытный разработчик это сделает легко даже на ассемблере, причём на автомате, ему не нужна помощь компилятора.
Видимо, популярные ОС, приложения под них, браузеры, виртуальные машины и все остальное пишут неопытные.
Я не спорю что языки типа Rust снижают количество очевидных ошибок, но всё равно, большей частью речь только об ошибках связанных с обращением к памятью, в редких случаях других очевидных ляпах (типа присваивание вместо сравнения как в C, хотя это может быть и намеренно) — но это не решает проблему с багами в целом, это лишь уменьшит их количество (ненамного — C/C++ и прочие «небезопасные» языки и так мало где используются уже).
Если оно уменьшает количество багов хотя бы в 2 раза, то это уже хороший такой толчок. А для этого есть все предпосылки.
Если даже «прям щаз» всё что написано на C/C++ перепишут на Rust, это не сократит количество багов и уязвимостей даже на половину — по крайней мере, до тех пор пока разработчики не станут намного более квалифицированными.
Конечно сократит — потому что компилятор явно не соберется там, где раньше была проблема. И у разработчика остается только либо исправить ошибку, либо написать unsafe, отстрелить ногу, и получить возврат кода на review, потому как проверить тыщи строк PR'а пытливым взглядом сильно труднее, чем зацепиться взглядом за unsafe
, и попробовать детально проанализировать чем он занимается.
В этом, собственно, и заключается моя мысль.
Никак. И это не считается за UB, это считается за ошибку логики приложения.
А как C++ решает проблему, когда есть ресурс, в который пишут из двух потоков, но забыли сделать mutex::lock? Rust эту проблему решает.
Да, я понял к чему вы ведете. Да, будет дедлок. Нет, раст от этого никак не защитит.
Rust is otherwise quite permissive with respect to other dubious operations. Rust considers it "safe" to:
- Deadlock
- Have a race condition
- Leak memory
- Fail to call destructors
- Overflow integers
- Abort the program
- Delete the production database
However any program that actually manages to do such a thing is probably incorrect. Rust provides lots of tools to make these things rare, but these problems are considered impractical to categorically prevent.
Конечно же, под памятью мы понимаем любые ресурсы, каналы там, сокеты, и всё-всё остальное.
По определению, никакой язык не в состоянии гарантировать ничего что выходит за рамки среды, которую он контролирует. Race может быть внешним, от языка не зависящим, он может быть gracefully processed (извините, не могу найти русский эквивалент), или может привести к проблемам. Собственно, про это явно говорится в документации к Rust.
Видимо, популярные ОС, приложения под них, браузеры, виртуальные машины и все остальное пишут неопытные.
Да, неопытные — большей частью. Тот факт что им удается сделать что-то работающим, нисколько не исключает тот факт что их способ — не самый оптимальный и не свободен от ошибок.
Это не значит что ничего не нужно делать, если не делать это хорошо — но факт остается фактом.
Если оно уменьшает количество багов хотя бы в 2 раза, то это уже хороший такой толчок. А для этого есть все предпосылки.
Неважно, сколько яда попадёт в ваш организм, если это смертельная доза. Мне, как потребителю, неважно, что программисты пофиксили 99% багов, если из за 1% отказали тормоза и я въехал в бетонную стену. Радуйтесь, что в большинстве случаев это не тормоза.
И у разработчика остается только либо исправить ошибку, либо написать unsafe, отстрелить ногу, и получить возврат кода на review, потому как проверить тыщи строк PR'а пытливым взглядом сильно труднее, чем зацепиться взглядом за unsafe, и попробовать детально проанализировать чем он занимается.
В этом и заключается проблема современных разработчиков.
Более чем 10 лет я писал write-only код, который вылизывался перед продакшн, потом работал более чем эти самые 10 лет без единой проблемы (и это был не Rust), и единственная поддержка в которой он нуждался — это хорошая документация. Увы, эти времена прошли, за последние 20 лет я не встретил (лично) никого кто был бы на такое способен. Печаль.
Да, неопытные — большей частью. Тот факт что им удается сделать что-то работающим, нисколько не исключает тот факт что их способ — не самый оптимальный и не свободен от ошибок.
Это не значит что ничего не нужно делать, если не делать это хорошо — но факт остается фактом.
Интересно, чем же таким интересным занимаются все опытные. Явно не ядра ОС пишут, и не новые языки. Да и ничего из популярного софта, ведь там регулярно то одна дыра, то другая.
Неважно, сколько яда попадёт в ваш организм, если это смертельная доза. Мне, как потребителю, неважно, что программисты пофиксили 99% багов, если из за 1% отказали тормоза и я въехал в бетонную стену. Радуйтесь, что в большинстве случаев это не тормоза.
Вот только не надо этих сказок про «чуть-чуть беременная». Качество кода — непрерывная величина, которая начиная с некоторого предела (за которым «абсолютная неработоспособность продукта») растет и растет. В винде куча багов, но она спокойно себе работает. Если бы багов стало в 2 раза меньше, это конечно же было заметно. Она была бы стабильнее, удобнее, и все такое. Но никто никуда не въезжает несмотря на текущее положение дел, хотя без этих багов жизнь была бы краше.
В этом и заключается проблема современных разработчиков.
Более чем 10 лет я писал write-only код, который вылизывался перед продакшн, потом работал более чем эти самые 10 лет без единой проблемы (и это был не Rust), и единственная поддержка в которой он нуждался — это хорошая документация. Увы, эти времена прошли, за последние 20 лет я не встретил (лично) никого кто был бы на такое способен. Печаль.
Значит, ваш код не особо был нужен. Или вы заливали код какого-нибудь вояджера, который запускался и делал одно и то же до конца своей жизни.
Обычно проекты растут функционально, и выходят за рамки изначально запланированных целей по нескольку раз. Сначала это просто оболочка для файлов, потом еще и музыкальльный проигрыватель, потом облачное хранилище для всего этого дела, и пошло-поехало…
К слову, не-write-only код в документации часто не особо нуждается. Точнее сам код и является документацией, хоть генерируй по нему.
Увы, эти времена прошли, за последние 20 лет я не встретил (лично) никого кто был бы на такое способен.Это не от программистов зависит, а от заказчиков.
Мне вот каждые 2-3 месяца прилетает такая ситуация. При создании первых версий оказывается, что некоторые очень важные бизнес сценарии будет сделать затратно (по времени). Заказчики клянутся, что такого нам точно не надо, и кое-то важное не закладывается в базу. Естественно, через полгода они начинают ныть, что им это надо, и вот прям сейчас, жить без этого не могут. Я им отвечаю: надо всё переписать, мы же при проектировании закладывались, согласовывали 3 раза, что такого точно не будет — вот вся переписка. Начальник же мне говорит — ничего переписывать не надо, херачь костылей побольше, но сделать надо быстро. Вот так всё и работает )))
их невозможно проверить статически, особенно если поведение программы в целом и потоков в частности зависит от внешних данных
На самом деле можно, и для некоторого класса рейсов вполне можно формально доказать, что их там нет.
Правда, мне не хватает знаний раста, чтобы что-то говорить про него или про тот папир.
да и документация не делает таких утверждений, даже наоборот
Дедлок /= рейс (и даже не принадлежит множеству рейсов, пожалуй).
Лично у меня чаще проблемы со значением, которые иногда получается через синхронизацию, а иногда бед, чем с попыткой получить кучу ресурсов в рандомном порядке.
На rust по-идее можно переписывать частями, т.к. линковку с С/С++ он поддерживает.
Потокобезопасность там достигается рантаймом и библиотеками, хотя если не использовать бездумно shared access (т.е. только обмен сообщениями с примитивами синхронизации) будет ровно то же самое что и в Rust.
Имеющийся код на C/C++ придётся именно переписывать на Rust (который ещё нужно изучить и понять, плюс поменять ряд концепций), в то время как в случае с D его придётся только адаптировать (хотя в случае C++ с тяжелыми темплейтами будет очень тяжко, они совсем разные).
Когда я начал изучать Rust, я понял что создание кода на нём это головная боль и существенно большие временные затраты по сравнению с C/C++/D/C#, не говоря уже об объеме кода (писать придётся больше при одинаковых задачах), а по сравнению с D/C# выигрыш весьма сомнителен (с точки зрения безопасности). К счастью, мне он нужен исключительно read-only (нужно сделать аудит одного проекта), это намного проще чем писать код.
Вы всё же почитайте про D на его сайте, вместо беглого гугления (это не займёт много времени) — и сравните с Rust, как по фичам так и по простоте использования (для сишников).
D позволяет писать небезопасный код (как и Rust, при желании), но по умолчанию он довольно безопасный. GC это часть стандартного рантайма, его можно отключить (когда нужно) — если не использовать стандартный рантайм (если нужно ручное управление).
Понятие "небезопасный" вы формализуйте. А то в одном случае у вас "холодная" погода в 10 градусов, а в другом — "горячий" сверхпроводник с температурой -200С.
Потокобезопасность там достигается рантаймом и библиотеками, хотя если не использовать бездумно shared access (т.е. только обмен сообщениями с примитивами синхронизации) будет ровно то же самое что и в Rust.
Если компилятор не бьет по рукам, то это не безопасность.
Имеющийся код на C/C++ придётся именно переписывать на Rust (который ещё нужно изучить и понять, плюс поменять ряд концепций), в то время как в случае с D его придётся только адаптировать (хотя в случае C++ с тяжелыми темплейтами будет очень тяжко, они совсем разные).
Не надо тешить себя надеждой, на D точно так же нужно переписывать. И в случае с D опять же никакой выгоды нет, мы не можем сказать "да, в этом коде нет багов", просто сделав grep по какому-нибудь ключевому слову.
Когда я начал изучать Rust, я понял что создание кода на нём это головная боль и существенно большие временные затраты по сравнению с C/C++/D/C#
Видимо, компилятор заставил проверить все edge-кейсы сразу? С непривычки может быть довольно напряжно, да. Только в продакшне это все равно придется решать, только позже. Классическая статика вс динамика.
не говоря уже об объеме кода (писать придётся больше при одинаковых задачах)
Да вроде нет, не придется. По крайней мере, если хотим выразить то же самое. А если выражаем больше, то инфы нужно предоставить больше, логично же.
Но учитывая, что большую часть времени мы читаем, то "лишняя писанина" только улучшает понимание кода. В шарпах например я часто пытаюсь понять, что за инстанс тут за интерфейсом скрывается. Потому что в шарпах принято писать с максимальной динамической диспетчеризацией. В расте был бы генерик, из которого всё очевидно.
Потокобезопасность там достигается рантаймом и библиотеками, хотя если не использовать бездумно shared access (т.е. только обмен сообщениями с примитивами синхронизации) будет ровно то же самое что и в Rust.
Если не использовать бездумно $dangerous_feature, то будет ровно то же самое что и в $safe_language.
Но лучше, когда компилятор бьёт по рукам.
На счет переписывания, мне понятно Ваше стремление, но нежелание потратить огромное время без видимой и сию минуту ощущаемой выгоды — для большинства людей это рационализм, а не лень.
Да никто не принижает плюсы.
Вот возьмем такой код
#include <memory>
int main () {
int* p = new int (10);
std::unique_ptr<int> a (p);
std::unique_ptr<int> b (p);
}
Что мне в этой ситуации делать? Не помогли ни умные указатели, ни move-семантика.
Обычно мне на такое отвечают, что ни один нормальный программист так писать не будет, и вообще пример искусственный. Ну, не знаю, насколько он там искусственный, но такие примеры делают неплохую прибыль для ребят вроде PVS Studio.
Ссылаясь на PVS Studio наверно стоит глянуть их блоги и посмотреть, какие именно ошибки чаще всего находит их анализатор. Обычно это неправильное использование ||/&& или другие вариации unreachable/unused code.
Я лично могу воспринимать ваш пост лишь как вброс.
во-первых, мув-семантики тут нет. Во-вторых, использование умных указателей подразумевает также создание объектов через соответствующие функции, для unique_ptr — make_unique.
Уверен, humbug может вам предоставить более жизненный пример.
Ссылаясь на PVS Studio наверно стоит глянуть их блоги и посмотреть, какие именно ошибки чаще всего находит их анализатор. Обычно это неправильное использование ||/&& или другие вариации unreachable/unused code.
Скорее всего просто потому, что их паттерны очевиднее. То есть вопрос «поиска ключей под фонарем». Если работа с умными указателями в 80% является ложноположительной, то никто не будет пользоваться таким инструментом, хотя это означает, что 20% реально баги. А если 20% выделения всей памяти это баги, то это катастрофа.
Окей, давайте сыграем по вашим правилам.
Вот реальный код, написанный по канонам С++17, но в нем в продакшне был обнаружен баг. Его достаточно легко найти, когда код изолирован, и про него сказано "тут ошибка", но в проекте на миллионы строк придется попотеть, прежде чем поймете, почему иногда поведение странное
std::vector<_> vec = ...;
auto it = vec.begin(), end = vec.end();
while (it != end) {
if (/* some conditions on `it` */) {
++it;
continue;
} else {
// ...
it = vec.erase(it);
}
}
PVS такое не очень находит, а вот Coverity, кстати, регулярно и вполне.
Ну и да, отдельно нужно подчеркнуть то, что вы написали: против такой ситуации спасает явный запрет new
. Голый new
— это как unsafe
.
И пример действительно искусственный, так как, судя по статьям от разработчиков PVS, такие баги встречаются довольно редко.
У Интернета могут быть серьёзные проблемы из-за языков, подобных C и C++, которые способствуют появлению уязвимостей