Недавно (10-11 июня) в Москве прошла очередная научно-практическая конференция OSDay. На этот раз конференция проходила в математическом институте им. В.А. Стеклова РАН. Формально она была посвящена инструментам разработки операционных платформ и системного программного обеспечения. Как обычно, темы, затрагиваемые на конференции, не ограничились формально заявленными, а поднятые вопросы рассматривались с разных сторон и обсуждались различные подходы к их решению. Различные взгляды и подходы — это, на мой взгляд, то, что выделяет конференцию среди остальных. Так, например, в конце второго дня конференции, буквально под занавес, Дмитрий Завалишин ( dzavalishin ), один из организаторов, спровоцировал бурную дискуссию, о том, что язык программирования Си вообще-то устарел и разрабатывать (в том числе и операционные системы) нужно, как минимум, на языках с управляемой памятью. Свое видение об этой дискуссии и других интересных мне темах, поднятых на конференции, я изложу в данной статье. Кому интересно прошу под кат.
Начну не с обзора докладов, а с выставки, которая является частью конференции. Несколько компаний показали свои разработки в области системного ПО. В основном это операционные системы, но, например, компания РЕД СОФТ кроме ОС представила СУБД “РЕД База данных” основанную на проекте “Firebird”. Об этой СУБД я уже упоминал при обзоре одной из прошлых конференций OSDay. Новой информацией для меня стало то, что она портирована на архитектуру Эльбрус.
Поддержка архитектуры Эльбрус была заявлена в продуктах и у других участников выставки. Информация о том, что ОС Альт-Linux исполняется на процессорах Эльбрус, конечно, не стала для меня новостью. Сотрудники Базальт-СПО, как обычно, привезли стенд на базе Эльбруса и продемонстрировали работу своей ОС на этой платформе. А вот то, что на баннере QP ОС, о которой я также несколько раз уже рассказывал в обзорах конференции, заявлена поддержка поцессоров Эльбрус, меня удивило. Ведь мы приложили немало усилий чтобы портировать Embox на данную архитектуру, о чем также писали на хабре. Выяснилось, что к сожалению, это не полноценный порт под архитектуру e2k, запуск был осуществлен в режиме трансляции команд x86, который, как известно, присутствует в процессорах Эльбрус.
Поддержка различных аппаратных платформ была фишкой всех участников выставки (за исключением компании РусБИТех -Астра, но у них, как известно, своя ниша). РЕД СОФТ показал свою РЕД ОС (если я правильно понял, то это наследник ГосЛинукс, который внесен в реестр отечественного ПО) на RaPi. У QP ОС была заявлена поддержка ARM. Но безусловно, самым кросс-платформенным выступил Альт-Линукс. Коллеги показали работу не только на отечественных Эльбрусе и Байкале, но и, например, на такой относительно редкой архитектуре как RISC-V.
Тема безопасности ПО очень широкая. На конференции несколько раз объясняли, что существуют несколько различных типов безопасности, точнее определений, что же такое безопасность. Происходят они от английских safety, security, reliability и так далее. Поэтому докладчик обычно говорил, о какой именно безопасности идет речь в данный момент. Хотя все сходились во мнении, что трудно говорить об информационной безопасности (security), если не обеспечена функциональная безопасность (safety).
Условность разделения на security — safety была хорошо заметна на секции, посвященной информационной безопасности. Например, Александр Попов ( a13xp0p0v ), разработчик ядра Linux, который на предыдущей конференции выступал с докладом “Как STACKLEAK улучшает безопасность ядра Linux”, представил доклад “Карта средств защиты ядра Linux”, и на карте видно, что ключ к информационной безопасности лежит в области качественного ПО. Ведь большинство проблем безопасности являются стандартными: переполнение буфера, переполнение стека, не очистка стека при возврате из системного вызова и т. д. Посмотреть его проект можно на github. Вчера опубликовали на хабре.
Проблема размытости понятия безопасности ПО, также была продемонстрирована в докладе Екатерины Рудиной из Лаборатории Касперского “Модель зрелости безопасности интернета вещей для установления, согласования и ограничения требований к операционным системам”. Из доклада следовало, что понятие безопасность может различаться в применении к разным сферам, и даже к разным типам устройств и продуктов. Что очевидно, ну зачем, например, на вашем фитнес браслете антивирус. Поэтому в Industrial Internet Consortium, в котором состоит и Лаборатория Касперского, предложили использовать модель зрелости безопасности интернета вещей (IoT Security Maturity Model, IoT SMM) для формулировки понятия безопасности для конкретного случая.
Думаю, по причине трудной отделяемости security и safety докладов по чистой информационной безопасности было не очень много. Ярким примером такого выступления был доклад от комиттера OpenSSL Дмитрия Белявского “Гостификация ПО: подход из мира Open Source”. В котором автор рассказал, о трудностях поддержки национальных стандартов по криптографии.
Функциональная безопасность (safety software) в том или ином виде присутствовала практически во всех докладах на конференции. Ведь если посмотреть глубже, то даже в уже упомянутой дискуссии по поводу устаревания языка Си подразумевалось, что данный язык небезопасен и с его помощью очень просто “выстрелить себе в ногу”.
Судя по докладам на конференции, улучшение функциональной безопасности (надежности) ПО участникам видится в применении инструментальных средств. Хотя, возможно, это дань заявленной теме конференции — инструменты. Поэтому подавляющее большинство докладов предлагало именно инструментальный подход. Один из организаторов конференции ИСП РАН специализируется на разработке инструментов для статического и динамического анализа кода. Собственно ИСП РАН и задал тон выступлением Александра Герасимова c докладом “Применение инструментов автоматического анализа программ в цикле разработки безопасного ПО”.
По теме разработки статических анализаторов был доклад от Владимира Козырева из компании Advalange “Разработка инструментария сбора и анализа покрытия бортового программного обеспечения”. Представленный инструментарий был разработан для целей верификации бортового ПО по стандарту DO-178C, но этот же инструментарий может быть использован не только в бортовом ПО, ведь анализируемый код на покрытие это обычный Си.
Кроме докладов про разработку инструментов, было несколько докладов про опыт использования подобных (или этих же) инструментов. Например, доклад Петра Девянина из РусБИТех-Астра с длинным названием “Опыт применения инструментальных средств для повышения доверия к механизмам защиты ОССН Astra Linux Special Edition” рассказывал об опыте применения этих инструментов к модулю системы безопасности для их ОС.
Естественно, на конференции были представлены не только инструменты анализа ПО но и другие, с помощью которых можно повысить надежность ПО. Очень интересно было послушать Дмитрия Дагаева с докладом “Масштабируемые Оберон-технологии как средства обеспечения защищенного ПО критически важных систем”. Автор доклада является главным конструктором SCADA СУОК для АЭС. Поэтому не понаслышке сталкивался с системами с “повышенными требованиями в части функциональной безопасности и защиты от кибер-угроз” (цитата из аннотации к его докладу). Для увеличение безопасности ПО автор предлагает использовать Оберон технологии. Автор языка Оберон Николаус Вирт, вложил идею внесения ограничений, что существенно уменьшает риск написания небезопасного ПО. При этом с помощью доработки компилятора автор доклада, предлагает создавать образы, нацеленные на различные задачи и платформы. Доклад был мне очень близок, поскольку мы в Embox пришли к похожим идеям по ограничениям. Но предложили ограничения вносить с помощью языка описания модулей ( декларативного языка собственного сочинения нацеленного на конкретную задачу). И для генерации артефактов позволяющих создавать образы под конкретную задачу, на наш взгляд, также проще использовать отдельный язык для описания этих артефактов.
В итоге организаторы конференции свели в одной секции доклады по различным подходам к безопасному ПО, речь в первую очередь о функциональной безопасности. Первый подход — использовать инструментарий для анализа кода, второй — использовать языки более высокого уровня и, наконец, подход лаборатории Касперского, который является скорее организационным или методическим. Был еще доклад про отладчик, но я лучше вынесу его в отдельную секцию, хотя, безусловно, отладка позволяет снизить количество ошибок и, следовательно, тоже увеличивает надежность ПО.
На конференции были представлены несколько средств отладки и профилирования системного ПО.
Валерий Егоров из компании НТП «Криптософт» (создатель QP ОС) рассказал об отладчике PathFinder, который используется в их гипервизоре QP VMM. Естественно, все свое, со всеми вытекающими достоинствами и недостатками.
Денис Силаков, старший системный архитектор, Virtuozzo
Рассказал об опыте поиска ошибок, основанном на ABRT (Automatic Bug Reporting Tool). Сборка лога всего, что может пригодиться для анализа, отправка отчета при возникновении внештатной ситуации на сервер, и дальнейший анализ уже на сервере.
Федор Чемерев из НИИСИ РАН рассказал про средства трассировки в ОС РВ семейства “Багет”. Поскольку ОСРВ “Багет” ориентирована на встраиваемые системы, то и в случае Virtuozzo на инструментальной машине происходит сбор информации, а анализ происходит на сервере. Сбор информации происходит путем записи в журнал событий, при этом журнал может анализировать и без внештатных ситуаций.
Первым докладом про инструментарий, способствующий модульности ПО и преимуществах модульности, был уже упомянутый доклад про Оберон технологии.
Кроме этого были еще целых три доклада, каждый из которых предлагал собственный подход к проблеме обеспечения модульности. Дмитрий Алексеев из ООО «Эремекс» представил доклад “Внедрение зависимостей в компонентно-ориентированном ПО на C/C++”. В нем автор рассказал о переключении конфигурации различных модулей ядра ОС FX-RTOS и также различных интерфейсов. Реализован проект на основе макросов. Подробнее в статье на хабре.
Я, Антон Бондарев, как участник проекта Embox, представил доклад “Опыт разработки и применения системы сборки на основе специализированного языка программирования”, в котором рассказал о нашем опыте разработки языка Mybuild о чем частично писали на хабре. В нашем случае модульность и внедрение зависимостей обеспечивается с помощью отдельных файлов, в которых на декларативном языке описываются модули.
И третий это доклад от Маллачиева Курбанмагомеда из ИСП РАН “Об использовании модульного подхода во встраиваемых операционных системах”. Данный инструмент был использован в еще одной ОС JetOS. Для описание модулей используется язык YAML. К сожалению, не было приведено примеров, но озвученная идея была очень интересна и мы ее обдумываем в нашем проекте. Идея заключается в том, чтобы экспортировать (декларировать) интерфейс и объекты могут подключаться именно через этот интерфейс. Была озвучена мысль, что авторы переизобрели IDL. Но это конечно не так, просто близкие идеи.
Такое количество докладов по модульному или компонентному подходу, наверное, указывает на важность компонентной модели, для создания надежного ПО. Ведь ни у кого не возникает сомнений в том, что модульный подход может уменьшить сложность ПО, а следовательно и его надежность; что правильная структура (архитектура) ПО дает поразительные результаты; что правильный API (по сути дела контракт для ПО) делает ПО более поддерживаемым. Но легче сказать о том, что нужно сделать правильный интерфейс, чем реализовать его. Например, в докладе про Оберон предполагается использовать модули без состояния. Естественно, это решает проблему, но лично я никогда не видел реальной системы, которая не имела бы состояния.
Проблемы применения языка Си очевидны, поэтому и применяются всевозможные способы их решения, и статические анализаторы, и различные виды тестирования, и еще много чего. Возникает резонный вопрос: а зачем тратить столько усилий?
Поскольку дискуссия была открытая и каждому желающему предоставлялся микрофон было хорошо видно, что часть участников конференции полностью поддержала данную идею, а часть высказала разного рода сомнения в том, что язык Си уйдет в прошлое, по крайней мере в области системного программирования в ближайшем будущем.
Сначала приведу аргументы той части участников, которая поддержала идею. Очевидно, что идею поддержал Дмитрий Дагаев, автор доклада про Оберон. В качестве аргумента он привел фотографию где, он на снимке с Николаусом Виртом держит плакат с надписью о том, что обучать программированию нужно только на Обероне. Другие участники дискуссии выдвинули тезис, что и архитектура фон Неймана, несколько устарела, ну как минимум можно использовать тегированную память, как в архитектуре Эльбрус. Причем речь шла не об архитектуре Эльбрус, а о современных тенденциях архитектуры ARM, и сообщил об этом уже упомянутый Александр Попов. Естественно, тут же нашлись желающие написать ОС, часть функций которой будет реализована аппаратно. Еще целый ряд участников, развивая тему использования другого языка, естественно, предложили использовать функциональные языки программирования. Развивая тему языка, пришли к выводу, что, оказывается, у нас в стране нет сертифицированных средств разработки, например, компилятора под ARM, да и компиляторы, которые разрешены к использованию, могут содержать закладки. Поэтому очевидно, что сначала нужно создать компилятор, а уж потом на его основе писать ПО, в том числе и операционные системы.
Аргументы второй части участников дискуссии, были не то чтобы в пользу использования языка Си, скорее они объясняли, почему этот язык до сих пор является стандартом для создания ядер ОС. Звучали такие аргументы. Синтаксис языка Си подразумевает полный и явный контроль программистом всего в программе, в том числе и выделения памяти, что позволяет создавать очень эффективные с точки зрения ресурсов алгоритмы. Язык Си, действительно, поддерживается средствами разработки, взять например gcc. Синтаксис языка очень простой и знаком очень большому количеству людей.
Мне очень понравилась аллегория с космолетами и старыми дорогами. Исходя из нее, сейчас используются обычные машины, которые, наверное, не очень хороши, загрязняют окружающую среду и имеют большую аварийность. Но для того, чтобы перейти на какие-нибудь беспилотные суперкары, наверное, нужно до них дорасти, построить сеть дорог соответствующего качества, заправки, разработать алгоритмы и так далее. Работы в этих направлениях ведутся, но чтобы вот так взять и запретить старые машины — такое вряд ли получится.
Абсолютно согласен, сначала нужно развить индустрию и обучить специалистов, а это очень долгие процессы, пока же приходиться использовать кучу уже разработанного ПО на языке Си, поскольку оно гораздо надежнее и более отлаженное, чем вновь созданное, пусть и на передовых технологиях. Ведь хоть и не на данной дискуссии, но на конференции звучали подобные предостережения. Например, автор доклада о гостификации криптографического ПО Дмитрий Белявский на вопрос, что нужно знать разработчику занимающемуся безопасностью, ответил, “никогда не пишите криптографию самостоятельно”. А Дмитрий Шевцов из ФСТЭК, попросил больше заботиться о поддержке разработанного ПО.
Про обучение специалистов, наверное, самый важный вопрос: на чем “думают“ специалисты — на том и будет разработано ПО, вполне возможно, что язык Си стал стандартом де факто для ОС, поскольку в нем были UNIX и Minix (а может, именно потому, что был задуман для разработки UNIX). Поэтому проект обучения школьников и студентов программированию на языке Оберон Информатика 21 может дать свои плоды, правда, должно пройти немало времени.
Как я уже сказал во введении, данная конференция позволяет делиться идеями, обсуждать и дискутировать. По многим вопросам были представлены несколько подходов, например, про модульное ПО и безопасное ПО. Причем организаторы конференции сознательно зовут докладчиков с разными подходами и это делает конференцию еще более интересной. Ну и конечно, конференция очень открытая, как сказал Дмитрий Завалишин в ходе дискуссии об языке Си, “Пять минут славы каждому“.
Только что прочитал статью на хабре под названием “ Технические СМИ как базар”. В ней объясняется, как важно иметь несколько различных мнений. Предлагаю продолжить дискуссию о языке Си на Хабре. Например, очень интересно узнать, есть ли кросс-платформенные промышленные решения на rust или go?
Выставка
Начну не с обзора докладов, а с выставки, которая является частью конференции. Несколько компаний показали свои разработки в области системного ПО. В основном это операционные системы, но, например, компания РЕД СОФТ кроме ОС представила СУБД “РЕД База данных” основанную на проекте “Firebird”. Об этой СУБД я уже упоминал при обзоре одной из прошлых конференций OSDay. Новой информацией для меня стало то, что она портирована на архитектуру Эльбрус.
Поддержка архитектуры Эльбрус была заявлена в продуктах и у других участников выставки. Информация о том, что ОС Альт-Linux исполняется на процессорах Эльбрус, конечно, не стала для меня новостью. Сотрудники Базальт-СПО, как обычно, привезли стенд на базе Эльбруса и продемонстрировали работу своей ОС на этой платформе. А вот то, что на баннере QP ОС, о которой я также несколько раз уже рассказывал в обзорах конференции, заявлена поддержка поцессоров Эльбрус, меня удивило. Ведь мы приложили немало усилий чтобы портировать Embox на данную архитектуру, о чем также писали на хабре. Выяснилось, что к сожалению, это не полноценный порт под архитектуру e2k, запуск был осуществлен в режиме трансляции команд x86, который, как известно, присутствует в процессорах Эльбрус.
Поддержка различных аппаратных платформ была фишкой всех участников выставки (за исключением компании РусБИТех -Астра, но у них, как известно, своя ниша). РЕД СОФТ показал свою РЕД ОС (если я правильно понял, то это наследник ГосЛинукс, который внесен в реестр отечественного ПО) на RaPi. У QP ОС была заявлена поддержка ARM. Но безусловно, самым кросс-платформенным выступил Альт-Линукс. Коллеги показали работу не только на отечественных Эльбрусе и Байкале, но и, например, на такой относительно редкой архитектуре как RISC-V.
Информационная безопасность
Тема безопасности ПО очень широкая. На конференции несколько раз объясняли, что существуют несколько различных типов безопасности, точнее определений, что же такое безопасность. Происходят они от английских safety, security, reliability и так далее. Поэтому докладчик обычно говорил, о какой именно безопасности идет речь в данный момент. Хотя все сходились во мнении, что трудно говорить об информационной безопасности (security), если не обеспечена функциональная безопасность (safety).
Условность разделения на security — safety была хорошо заметна на секции, посвященной информационной безопасности. Например, Александр Попов ( a13xp0p0v ), разработчик ядра Linux, который на предыдущей конференции выступал с докладом “Как STACKLEAK улучшает безопасность ядра Linux”, представил доклад “Карта средств защиты ядра Linux”, и на карте видно, что ключ к информационной безопасности лежит в области качественного ПО. Ведь большинство проблем безопасности являются стандартными: переполнение буфера, переполнение стека, не очистка стека при возврате из системного вызова и т. д. Посмотреть его проект можно на github. Вчера опубликовали на хабре.
Проблема размытости понятия безопасности ПО, также была продемонстрирована в докладе Екатерины Рудиной из Лаборатории Касперского “Модель зрелости безопасности интернета вещей для установления, согласования и ограничения требований к операционным системам”. Из доклада следовало, что понятие безопасность может различаться в применении к разным сферам, и даже к разным типам устройств и продуктов. Что очевидно, ну зачем, например, на вашем фитнес браслете антивирус. Поэтому в Industrial Internet Consortium, в котором состоит и Лаборатория Касперского, предложили использовать модель зрелости безопасности интернета вещей (IoT Security Maturity Model, IoT SMM) для формулировки понятия безопасности для конкретного случая.
Думаю, по причине трудной отделяемости security и safety докладов по чистой информационной безопасности было не очень много. Ярким примером такого выступления был доклад от комиттера OpenSSL Дмитрия Белявского “Гостификация ПО: подход из мира Open Source”. В котором автор рассказал, о трудностях поддержки национальных стандартов по криптографии.
Функциональная безопасность
Функциональная безопасность (safety software) в том или ином виде присутствовала практически во всех докладах на конференции. Ведь если посмотреть глубже, то даже в уже упомянутой дискуссии по поводу устаревания языка Си подразумевалось, что данный язык небезопасен и с его помощью очень просто “выстрелить себе в ногу”.
Судя по докладам на конференции, улучшение функциональной безопасности (надежности) ПО участникам видится в применении инструментальных средств. Хотя, возможно, это дань заявленной теме конференции — инструменты. Поэтому подавляющее большинство докладов предлагало именно инструментальный подход. Один из организаторов конференции ИСП РАН специализируется на разработке инструментов для статического и динамического анализа кода. Собственно ИСП РАН и задал тон выступлением Александра Герасимова c докладом “Применение инструментов автоматического анализа программ в цикле разработки безопасного ПО”.
По теме разработки статических анализаторов был доклад от Владимира Козырева из компании Advalange “Разработка инструментария сбора и анализа покрытия бортового программного обеспечения”. Представленный инструментарий был разработан для целей верификации бортового ПО по стандарту DO-178C, но этот же инструментарий может быть использован не только в бортовом ПО, ведь анализируемый код на покрытие это обычный Си.
Кроме докладов про разработку инструментов, было несколько докладов про опыт использования подобных (или этих же) инструментов. Например, доклад Петра Девянина из РусБИТех-Астра с длинным названием “Опыт применения инструментальных средств для повышения доверия к механизмам защиты ОССН Astra Linux Special Edition” рассказывал об опыте применения этих инструментов к модулю системы безопасности для их ОС.
Естественно, на конференции были представлены не только инструменты анализа ПО но и другие, с помощью которых можно повысить надежность ПО. Очень интересно было послушать Дмитрия Дагаева с докладом “Масштабируемые Оберон-технологии как средства обеспечения защищенного ПО критически важных систем”. Автор доклада является главным конструктором SCADA СУОК для АЭС. Поэтому не понаслышке сталкивался с системами с “повышенными требованиями в части функциональной безопасности и защиты от кибер-угроз” (цитата из аннотации к его докладу). Для увеличение безопасности ПО автор предлагает использовать Оберон технологии. Автор языка Оберон Николаус Вирт, вложил идею внесения ограничений, что существенно уменьшает риск написания небезопасного ПО. При этом с помощью доработки компилятора автор доклада, предлагает создавать образы, нацеленные на различные задачи и платформы. Доклад был мне очень близок, поскольку мы в Embox пришли к похожим идеям по ограничениям. Но предложили ограничения вносить с помощью языка описания модулей ( декларативного языка собственного сочинения нацеленного на конкретную задачу). И для генерации артефактов позволяющих создавать образы под конкретную задачу, на наш взгляд, также проще использовать отдельный язык для описания этих артефактов.
В итоге организаторы конференции свели в одной секции доклады по различным подходам к безопасному ПО, речь в первую очередь о функциональной безопасности. Первый подход — использовать инструментарий для анализа кода, второй — использовать языки более высокого уровня и, наконец, подход лаборатории Касперского, который является скорее организационным или методическим. Был еще доклад про отладчик, но я лучше вынесу его в отдельную секцию, хотя, безусловно, отладка позволяет снизить количество ошибок и, следовательно, тоже увеличивает надежность ПО.
Средства отладки
На конференции были представлены несколько средств отладки и профилирования системного ПО.
Валерий Егоров из компании НТП «Криптософт» (создатель QP ОС) рассказал об отладчике PathFinder, который используется в их гипервизоре QP VMM. Естественно, все свое, со всеми вытекающими достоинствами и недостатками.
Денис Силаков, старший системный архитектор, Virtuozzo
Рассказал об опыте поиска ошибок, основанном на ABRT (Automatic Bug Reporting Tool). Сборка лога всего, что может пригодиться для анализа, отправка отчета при возникновении внештатной ситуации на сервер, и дальнейший анализ уже на сервере.
Федор Чемерев из НИИСИ РАН рассказал про средства трассировки в ОС РВ семейства “Багет”. Поскольку ОСРВ “Багет” ориентирована на встраиваемые системы, то и в случае Virtuozzo на инструментальной машине происходит сбор информации, а анализ происходит на сервере. Сбор информации происходит путем записи в журнал событий, при этом журнал может анализировать и без внештатных ситуаций.
Модульный подход
Первым докладом про инструментарий, способствующий модульности ПО и преимуществах модульности, был уже упомянутый доклад про Оберон технологии.
Кроме этого были еще целых три доклада, каждый из которых предлагал собственный подход к проблеме обеспечения модульности. Дмитрий Алексеев из ООО «Эремекс» представил доклад “Внедрение зависимостей в компонентно-ориентированном ПО на C/C++”. В нем автор рассказал о переключении конфигурации различных модулей ядра ОС FX-RTOS и также различных интерфейсов. Реализован проект на основе макросов. Подробнее в статье на хабре.
Я, Антон Бондарев, как участник проекта Embox, представил доклад “Опыт разработки и применения системы сборки на основе специализированного языка программирования”, в котором рассказал о нашем опыте разработки языка Mybuild о чем частично писали на хабре. В нашем случае модульность и внедрение зависимостей обеспечивается с помощью отдельных файлов, в которых на декларативном языке описываются модули.
И третий это доклад от Маллачиева Курбанмагомеда из ИСП РАН “Об использовании модульного подхода во встраиваемых операционных системах”. Данный инструмент был использован в еще одной ОС JetOS. Для описание модулей используется язык YAML. К сожалению, не было приведено примеров, но озвученная идея была очень интересна и мы ее обдумываем в нашем проекте. Идея заключается в том, чтобы экспортировать (декларировать) интерфейс и объекты могут подключаться именно через этот интерфейс. Была озвучена мысль, что авторы переизобрели IDL. Но это конечно не так, просто близкие идеи.
Такое количество докладов по модульному или компонентному подходу, наверное, указывает на важность компонентной модели, для создания надежного ПО. Ведь ни у кого не возникает сомнений в том, что модульный подход может уменьшить сложность ПО, а следовательно и его надежность; что правильная структура (архитектура) ПО дает поразительные результаты; что правильный API (по сути дела контракт для ПО) делает ПО более поддерживаемым. Но легче сказать о том, что нужно сделать правильный интерфейс, чем реализовать его. Например, в докладе про Оберон предполагается использовать модули без состояния. Естественно, это решает проблему, но лично я никогда не видел реальной системы, которая не имела бы состояния.
Возвращаясь к дискуссии об устаревшем Си
Проблемы применения языка Си очевидны, поэтому и применяются всевозможные способы их решения, и статические анализаторы, и различные виды тестирования, и еще много чего. Возникает резонный вопрос: а зачем тратить столько усилий?
Поскольку дискуссия была открытая и каждому желающему предоставлялся микрофон было хорошо видно, что часть участников конференции полностью поддержала данную идею, а часть высказала разного рода сомнения в том, что язык Си уйдет в прошлое, по крайней мере в области системного программирования в ближайшем будущем.
Сначала приведу аргументы той части участников, которая поддержала идею. Очевидно, что идею поддержал Дмитрий Дагаев, автор доклада про Оберон. В качестве аргумента он привел фотографию где, он на снимке с Николаусом Виртом держит плакат с надписью о том, что обучать программированию нужно только на Обероне. Другие участники дискуссии выдвинули тезис, что и архитектура фон Неймана, несколько устарела, ну как минимум можно использовать тегированную память, как в архитектуре Эльбрус. Причем речь шла не об архитектуре Эльбрус, а о современных тенденциях архитектуры ARM, и сообщил об этом уже упомянутый Александр Попов. Естественно, тут же нашлись желающие написать ОС, часть функций которой будет реализована аппаратно. Еще целый ряд участников, развивая тему использования другого языка, естественно, предложили использовать функциональные языки программирования. Развивая тему языка, пришли к выводу, что, оказывается, у нас в стране нет сертифицированных средств разработки, например, компилятора под ARM, да и компиляторы, которые разрешены к использованию, могут содержать закладки. Поэтому очевидно, что сначала нужно создать компилятор, а уж потом на его основе писать ПО, в том числе и операционные системы.
Аргументы второй части участников дискуссии, были не то чтобы в пользу использования языка Си, скорее они объясняли, почему этот язык до сих пор является стандартом для создания ядер ОС. Звучали такие аргументы. Синтаксис языка Си подразумевает полный и явный контроль программистом всего в программе, в том числе и выделения памяти, что позволяет создавать очень эффективные с точки зрения ресурсов алгоритмы. Язык Си, действительно, поддерживается средствами разработки, взять например gcc. Синтаксис языка очень простой и знаком очень большому количеству людей.
Мне очень понравилась аллегория с космолетами и старыми дорогами. Исходя из нее, сейчас используются обычные машины, которые, наверное, не очень хороши, загрязняют окружающую среду и имеют большую аварийность. Но для того, чтобы перейти на какие-нибудь беспилотные суперкары, наверное, нужно до них дорасти, построить сеть дорог соответствующего качества, заправки, разработать алгоритмы и так далее. Работы в этих направлениях ведутся, но чтобы вот так взять и запретить старые машины — такое вряд ли получится.
Абсолютно согласен, сначала нужно развить индустрию и обучить специалистов, а это очень долгие процессы, пока же приходиться использовать кучу уже разработанного ПО на языке Си, поскольку оно гораздо надежнее и более отлаженное, чем вновь созданное, пусть и на передовых технологиях. Ведь хоть и не на данной дискуссии, но на конференции звучали подобные предостережения. Например, автор доклада о гостификации криптографического ПО Дмитрий Белявский на вопрос, что нужно знать разработчику занимающемуся безопасностью, ответил, “никогда не пишите криптографию самостоятельно”. А Дмитрий Шевцов из ФСТЭК, попросил больше заботиться о поддержке разработанного ПО.
Про обучение специалистов, наверное, самый важный вопрос: на чем “думают“ специалисты — на том и будет разработано ПО, вполне возможно, что язык Си стал стандартом де факто для ОС, поскольку в нем были UNIX и Minix (а может, именно потому, что был задуман для разработки UNIX). Поэтому проект обучения школьников и студентов программированию на языке Оберон Информатика 21 может дать свои плоды, правда, должно пройти немало времени.
Заключение
Как я уже сказал во введении, данная конференция позволяет делиться идеями, обсуждать и дискутировать. По многим вопросам были представлены несколько подходов, например, про модульное ПО и безопасное ПО. Причем организаторы конференции сознательно зовут докладчиков с разными подходами и это делает конференцию еще более интересной. Ну и конечно, конференция очень открытая, как сказал Дмитрий Завалишин в ходе дискуссии об языке Си, “Пять минут славы каждому“.
P.S.
Только что прочитал статью на хабре под названием “ Технические СМИ как базар”. В ней объясняется, как важно иметь несколько различных мнений. Предлагаю продолжить дискуссию о языке Си на Хабре. Например, очень интересно узнать, есть ли кросс-платформенные промышленные решения на rust или go?
lamerok
Основная проблема Си есть его же преимущество:
— он требует очень внимательного отношения к разработке софта, очень легко сделать функциональные ошибки, которые трудно отловить по причине этого полного контроля со стороны программиста. Т.е. грубо говоря, программист и есть слабое звено тут, причем в языке Си это особенно часто проявляется.
Согласен отчасти, много софта есть которое временем проверено. Но возьмем HAL для Stm, сколько люди его пользуют? А баги приводящие к отказу где-нить на трубопроводе на каком-нибудь автомате до сих пор люди ловят, да что там HAL, заголовочники на Си для микроконтроллеров, написанные производителем содержат ошибки (например по выравниванию структур). Конечно есть много сертифицированных Сишных библиотек к ним доверия больше, но бывают случаи даже SIL3 операционки выдают такие фокусы из-за макроса… Правда надо сказать, что большинство таких сертификатов получается за «Проверенно временем»
GCC кстати не рекомендован для использования при разработке надежного софта.
abondarev Автор
Абсолютно согласен! Но подразумевается что при написании ядра ОС, ну внимательнее разработчики должны что ли быть :) А взять например язык более высокого уровня, кто сказал что разработчики компилятора или рантайма (виртуальной машины) не сделают ошибку?
На мой взгляд HAL для stm ок относительно свежий, врядли можно сравнивать с Unix или теми же Виндами, там проверка временем и количеством использования сильно больше!
Так может это и есть правильный подход? :)
TonyLorencio
А что рекомендуют и обычно используют?
hhba
То, на что есть соответствующие сертификаты. Например, если вы сертифицируете свои разработки под 50128, то у вас емнип нет альтернатив к iar c compiler (это из популярных).
lamerok
GreenHills, IAR 8.22 только тот, что с сертификатом.
hhba
Мне казалось, что у GHS нет сертификата для 50128. Впрочем у них достаточно других сертификатов.
UPD: Да, где были мои глаза — есть!
lamerok
GreenHills, и IAR 8.22.3 только тот, что с сертификатом.
hhba
Вот тут я не понял. Как смена языка (с Си на Раст например) спасет вас от грубых ошибок производителя в msp/bsp?
lamerok
Если производитель, например, будет заголовочники предоставлять не на Си, а на С++, то можно избежать всякой ерунды…
Ну вот пример, STM предоставила flashloader для IAR… Если что файл лежит тут для IAR 8.20
EmbeddedWorkbench8.1\arm\src\flashloader\ST\FlashSTM32F4xx\inc:
Alexey_Alive
На чистом Си тоже есть static_assert прямой в стандарте (_Static_assert). Для выравнивания есть оператор offsetof, правда нет нормальной стандартной реализации, но огромное количество компиляторов поддерживают его с помощью builtin.
lamerok
Ага, видимо заголовочники писались до С11 стандарта
Ryppka
А в C99 можно получить тот же эффект с помощью умело написанного enum.
mayorovp
Хм, а что за случаи такие хитрые? Вроде бы тут выравнивания не должно появиться…
Или его макрос __IO добавляет?
lamerok
Общий случай, выравнивание по 4 байта, идет 16 битный инт, потом дырка в 2 байта, потом 16 битный инт RESERVED, потом дырка в 2 байта. И компилятор имеет на это полное право, он же не обязан за вас додумывать, что вы хотите два 16 битных инта запихать в одну ячейку памяти 32 битную и в итоге сделает размер этой структуры в 2 раза больше ожидаемого и адреса регистров не те, что ожидает программист. Компиляторы конечно не такие тупые, чтобы дырки всавлять, но в общем случае они должны это сделать исходя из архитектуры микропроцессора. Любой статический анализатор кода руганется жестко с сообщение уровня Ошибка.
_IO это volatile.
KanuTaH
Ну право-то он имеет, согласен (чтобы не имел, нужен __attribute__(packed)). Но обычно компиляторы выравнивают поля структур на их размер, то есть char'ы выравниваются побайтно, int16 на 2 байта, int32 — на 4 байта. То есть могут быть дырки в промежутках между char и int16 или int16 и int32, но не между полями одинакового размера (если их, конечно, не выравнивают специально каким-то нестандартным образом через соответствующий атрибут).
lamerok
Да это скорее всего так для IAR, но точно ли это будет так для другого компилятора?
Some Arm cores require that when accessing data in memory, the data must be aligned.
Each element in a structure must be aligned according to its specified type requirements.
This means that the compiler might need to insert pad bytes to keep the alignment correct.
KanuTaH
Ну все зависит от этих requirements. Теоретически можно представить себе архитектуру, которая будет требовать выравнивать int16 по 32-битной границе, но лично я такую безумную архитектуру сходу назвать затрудняюсь.
Ryppka
А что, адреса 16-битных регистров ввода-вывода выровнены по границам 2 байт?
lamerok
Как же они 16 битные, когда архитектура 32 бита. Они 32 битные, просто старшие 16 бит не используются…
Ryppka
И какой же вывод? Каковы адрес и смещение относительно базы рассматриваемого 16-битного регистра? Каковы адрес и смещение относительно базы следующего поля? Не на тот ли самый слоп больше?
lamerok
вывод такой, мы не можем гарантировать, что компилятор сделает то, что мы задумали и не вставит дырки, и поэтому такую структуру без выравнивания использовать нельзя… и надо бы её переделать для данного микроконтроллера вот в такую:
KanuTaH
Лучше явно указать компилятору необходимость упаковки структуры с помощью соответствующей прагмы или атрибута. Ваш вариант тоже ничего не гарантирует в общем случае, компилятор все еще волен делать любые padding'и, только уже между int32-полями :) На самом деле это обязательно нужно делать при написании переносимого кода, для работы которого важны смещения внутри структур, но если код де-факто не будет переносимым (предполагается работа на конкретной архитектуре и сборка конкретным компилятором), то этим часто пренебрегают.
lamerok
Нет для 32 битной машины выравнивание по умолчанию 4. считайте стоит pragma(4). Прагма непереносимый код, поэтому не надо её использовать. А гарантировать можно с помощью static_assert. Если вдруг этот код будете запускать на 64 битной машине, он вывалится с ошибкой… Но если уж вы хотите переносить на все типы машин, то тогда нужно делать, что-то типа этого:
Но если совсем нет доверия, то лучше тогда вообще такие структуры не использовать и напрямую с адресами регистров работать типа такого:
Вот тут можно почитать
KanuTaH
Ну если что-то такое считается «по умолчанию», то код по определению непереносимый :) Типа рассчитан на нормальную работу только на 32-битной архитектуре.
Если есть уверенность, что компиляторы и кросс-компиляторы для целевых архитектур ее поддерживают, то ее вполне можно использовать (для надежности добавив проверку размера структуры через static assert). Потому что это удобно. Подавляющее большинство мейнстримовых компиляторов (в том числе IAR) в нее умеют. Если такой уверенности нет, то тогда да, скорее всего придется работать напрямую с адресами регистров.
hhba
Что, внезапно, еще более общО и переносимо.
Ryppka
Гарантировать нечего: компилятор не вставит дырки только если это указано в его настройках или параметрах вызова. Покажите пример, где эту структуру размещают в памяти. И пример, где наличие слопа приводит к проблемам, но в реально работающим коде, а не в выдуманном…
lamerok
Я не могу привести код, потому что текущий IAR такого не позволяет, но это не означает, что его нет… сам же IAR пишет:
All data types must have a size that is a multiple of their alignment. Otherwise, only the first element of an array would be guaranteed to be placed in accordance with the alignment requirements.
Every C data object has an alignment that controls how the object can be stored in memory. Should an object have an alignment of, for example, 4, it must be stored on an address that is divisible by 4.
The reason for the concept of alignment is that some processors have hardware limitations for how the memory can be accessed.
Assume that a processor can read 4 bytes of memory using one instruction, but only when the memory read is placed on an address divisible by 4. Then, 4-byte objects, such as long integers, will have alignment 4.
A structure type will have the same alignment as the structure member with the most strict alignment.
Кстати не зря же в поздних версиях CMSIS эти заголовочники поправили…
Ryppka
Представленные структуры в плане смещения от начала структуры значимых полей идентичны. Вы пишете в регистр UART 16-битное значение или 32-битное? Каковы требования к выравниванию 16-битного целого на 32-битном ARM CortexM? Каков адрес следующего поля структуры типа short при выравнивании по умолчанию на этой платформе? Вы уверены, что проверка static_assert(sizeof(Uart) == sizeof(uint16_t) * 14); не выполнится?
Вроде бы 16-битные поля в данном случае будут выровнены по четной границе, не по 4 байтам, если это не особенность IAR.
Из врожденной скромности IAR по рукой не имеется, но и gcc-none-arm-eabi и armcc говорят, что все нормально.
Соглашусь, что добиваться верного выравнивания с помощью явных полей анахронизм, но допустимо. Я бы сделал __attribute__((aligned(4))) добавил, чтобы стало так, как Вы хотите, но можно было бы пользоваться uint16_t без приведения типа.
hhba
Может проще объявлять все регистры 32-битными, каковыми они и являются? Всегда лучше быть честным, чем умным.
Впрочем и это не снимает полностью вопрос переносимости.
Ryppka
А они, регистры, 32-битные? На железе?
Адреса MMIO регистров 32-битные, а регистры на железе могут быть и 8-, и 16-, и 32-, и, подозреваю, даже 64-битными. В языке C, а вслед за ним в C++ это явно не выражается, по крайней мере пока: ISO/IEC TR 18037 висит непринятым, хотя нужен не только во встроенных системах.
Вот и получается разной степени костыльные решения для того, чтобы сделать адреса 16-битных регистров правильно расположенными относительно базового адреса в ситуации, когда адреса регистра должны начинаться по границе 4 байт, а выравнивание 16-битного поля структуры по умолчанию — 2 байта. Или все прятать за кучей неприглядных макросов/инлайн-функций. Или как-то совмещать эти методы.
Что до переносимости, то сила C именно в том, что можно сделать непереносимые решения, там и когда это нужно. Чем ближе к железу, тем меньше переносимости и больше трюков, расширений компилятора и т.д.
В силу изложенного не могу сказать, что решение инженетов STMicro чем-то хуже или лучше, чем обмазывания 4-х записей в регистры кучей std::enable_if.
hhba
Могу ошибаться, но по-моему конкретно эти регистры 32-битные заложены в железе (а не просто отображены как 32-битные), по крайней мере обратное не указано явно.
Абсолютно любыми, зависит от железа. И когда у меня, например, в контроллере были некоторые регистры 8-битные, а некоторые 16-битные, то я предпочитал 16-битные адресовать половинками, для уверенности (сей подход не рекламирую). Правда там все равно шина данных была 8-битная и регистры физически на ней стояли, так что своя кухня в некотором роде.
Как интересно, ничего не знал об этом стандарте… Интересно, что в нем планируется внедрить, и как это увяжется с существующим развитием языка.
И это адище какое-то. Если вдруг вам понадобится 8-битный регистр среди кучи других регистров, то потребуется за ним гуськом расположить три таких же поля… И строго, очень строго следить за тем, чтобы кто-нибудь где-то в топе модуля не вписал pragma pack (2) например.
В этом смысле я считаю более консистентным подход с отдельным доступом к отдельным регистрам через указатели. Это правда требует больше работы с прямыми адресами, что само по себе не очень хорошо.
С этим не спорю.
Ryppka
Добро пожаловать в реальный мир низкоуровневого программирования)))
hhba
Вы так говорите, будто я не живу в этом мире с самого института ))
Ryppka
Тоже могу ошибаться, но на железе они вроде бы могут быть 16-битными, а могут быть и 32-битными. В конкретной аппаратной реализации они 16-битные, поэтому старшее слово в 32-битных (с точки зрения memory map) регистрах зарезервировано. Адреса этих регистров да, будут кратны 4 байтам. И если убрать тот или иной способ указать реальное выравнивание 16-битных uint16_t volatile xx, то будет запись/чтение зарезервированной части регистра с понятными последствиями. На сегодняшний день я не знаю красивого и эффективного решения подобных проблем.
hhba
Простите, а вы это знаете, или предполагаете?
Простой пример из практики: CPLD-сателлит у процессора, внутри нее есть набор 32-битных регистров, у большинства из которых доступна для использования только младшая половина, остальное зарезервировано (физически туда писать можно, ничего страшного не произойдет, просто смысла нет). В документации, как и полагается, старшее слово обозначено как reserved, однако регистр от этого 16-битным не становится. Конечно в микроконтроллере ситуация чуть иная, и скорее всего неиспользуемые регистры (которые будут только место занимать) физически отсутствуют, однако это не мешает адресным дешифраторам прикидываться валенком.
Если мы используем структуру для доступа к регистрам — то да, суровое танго.
Ryppka
Как там конкретно в железе даже не задумывался. Я знаю, что «работает» только изменение младших 16 бит по адресу 32-битного целого и что если объявить этот адрес адресом 16-битного целого — то это будет работать.
А вот можно ли без неприятных последствий записать по этому адресу 32-битное целое с мусором в старшем слове — не проверял. И не очень-то хочется.
hhba
Вот именно! То есть проблема уже на уровне описания регистров, буквально в голове у писавшего.
AVI-crak
Какое там выравнивание? Адрес структуры напрямую прописан, его можно принять и передать — но не изменить.
lamerok
Выравнивание по полям структуры 16 битный int выравнивается на 4 байта, ячейки памяти то 32 битные, на не 16.
AVI-crak
Ну не может uint16_t в структуре с фиксированным адресом внезапно занять 4 байта, typedef мешает.
А вот в новой структуре созданной например так:
USART_TypeDef new_usart;
размер переменных может быть увеличен в угоду ускорения общего алгоритма. Но для этого ещё постараться надо.
lamerok
Просто чтобы не лезть в дебри, читаем документацию на компилятор:
Some Arm cores require that when accessing data in memory, the data must be aligned.
Each element in a structure must be aligned according to its specified type requirements.
This means that the compiler might need to insert pad bytes to keep the alignment
correct.
There are situations when this can be a problem:
? There are external demands; for example, network communication protocols are
usually specified in terms of data types with no padding in between
Efficient coding for embedded applications
? You need to save data memory.
Use the #pragma pack directive or the __packed data type attribute for a tighter
layout of the structure. The drawback is that each access to an unaligned element in the structure will use more code.
Alternatively, write your own customized functions for packing and unpacking
structures. This is a more portable way, which will not produce any more code apart
from your functions. The drawback is the need for two views on the structure data—
packed and unpacked.
AVI-crak
Читайте внимательнее!!! Сказано о структуре созданной пользователем, когда адрес структуры выбирает компилятор.
Фиксированный адрес + typedef — запрещает всякую самодеятельность компилятору. Адреса всех элементов структуры, а также их размеры — известны ещё до начала компиляции. Выравнивание не выполняется.
mayorovp
Смотрите. Допустим, у нас есть две одинаковые структуры, одна по фиксированному адресу, вторая по выбранному компилятором. Мы копируем одну структуру в другую через memcpy. Что должно получиться?
LeonidPr
А там нигде в начале файла нет: #pragma pack(1)?
Который просто на весь файл распространяется.
lamerok
Посмотрел, нету…
hhba
То же самое предположил. Иначе как оно работает? Разве что на самом деле потом никак не используется…
hhba
Ну стоп, а в чем проблема-то? Ну оказались поля на самом деле по четыре байта, а не по два, кому от этого плохо? Аааа, кажется я догадываюсь… Наверное кто-то потом решил, что эта структура в памяти расположена сплошняком без промежутков между полями, и значит можно с ней работать как с массивом? Ну так ССЗБ, не?
Вообще пример конечно красивый, тут вам не откажешь, прямо руки тянутся… Но нет, слишком плохо я знаю плюсы. И я такой не один!
mayorovp
Судя по volatile-полям, один из экземпляров этой структуры располагается в памяти по фиксированному адресу, и должен этими самыми volatile-полями накрывать отображенные в память порты ввода-вывода.
hhba
Да, я понял, про то и пишу — воспринимать эту структуру как линейный массив (чего угодно, в том числе регистров) в общем случае нельзя. И хотя это очень распространенный прием (и от него трудно убежать — например я из-за лени использую STM HAL и пожинаю сопутствующие плоды), но мне он очень не нравится, поскольку опускает нас с уровня языка на уровень понимания его трансляции. Отсюда все эти сакральные знания про gcc aligned и ему подобное.
Добавлю, что дело не только в необходимости держать в голове выравнивание, нужно еще как-то защититься от случайных ошибок вида «вставили поле, не подумав про смещения». Я это встречал, и после такого вся красота использования структур для отображения регистров теряется.
Ryppka
В анализе и высказываниях по поводу этой структуры неплохо учитывать реальные требования к выравниванию полей структур и адресов MMIO.
hhba
Не неплохо, а необходимо. Либо можно просто отказаться от использования структур для доступа к группам регистров (но здесь есть свои минусы).
amartology
abondarev Автор
Все таки относительно редкой, поскольку довольно новая.
Безусловно перспективная, согласен самая быстрорастущая, но посмотрите например сколько дистрибутивов Linux поддерживает ARM и MIPS, а сколько RISC-V? До недавнего времени, это было скорее встроенное решение на основе ядер ПЛИС.
torgeek
Вопрос про использование Rust вместо Си уже отчётливо задают в разных проектах разработки ОС, компиляторов и аппаратных средсв.
Вот например, цитата из FAQ проекта Keystone-enclave – открытого каркаса TEE (Trusted Execution Environments) для процессоров и микроконтроллеров с системой команд RISC-V:
Q: Why are enclaves/SM/etc written in C? Why not Rust (or another modern language)?
A: Rust RV64 support was unavailable when Keystone was started. Few options for the security monitor besides C were available. We are keeping a close eye on Rust support as it matures for RV64, and expect to support it for enclaves at a minimum.
abondarev Автор
Абсолютно согласен. Rust очень интересен, и мы в Embox на него тоже облизываемся, но пока речь идет о пробе пера, каком нибудь модуле на Rust.
Он безусловно растет, но я лично о нем уже лет 5 назад слышал. И задавали все тот же вопрос, почему не на rust? Он такой хороший надежный, решает много очевидных проблем Си. Но когда речь заходила, а почему сами не используете, тут же «у нас продакшен мы не может экспериментировать». :)
TargetSan
Как по мне, в этом и проблема. Все ждут пока кто-нибудь другой вложится в поддержку архитектуры или тулчейна. Никто не хочет инвестировать ресурсы, даже крупные компании. Получается замкнутый круг.
abondarev Автор
Ну почему же никто. Если бы не вкладывались, хотя бы на уровне исследований, то врядли бы и до такого уровня rust бы дорос. Вкладываются и довольно много, но вот почему он не выходит прямо в массы это вопрос.
TargetSan
Я конкретно про embedded. Пока кроме проектов Japaric и ведомой им embedded working group не видно ничего. Думаю, если сравнить с тем, сколько вкладывается в поддержку С в тулчейнах, разница будет порядка на 3. Если не больше.
Halt
В смысле никого? www.tockos.org
TargetSan
Я не вижу там в контрибьюторах хоть какие-то коммерческие компании. Подобный проект — это замечательно. Но он хорошо иллюстрирует проблему во многих областях. Ниша нарастила определённую массу, стабилизировалась и "окуклилась". С одной стороны — много зрелых инструментов. С другой — для захода в нишу жизненно необходимо интегрироваться с тем, что есть — C-based тулчейнами.
abondarev Автор
Думаю сильно больше. Но не стоит забывать, что коммерческие компании должны еще и прибыль генерить, в Си огромная готовая инфраструктура, в которую ты вкладываешь и используешь кучу готового. В Rust пока такого нет, точнее это не сопоставимо по объемам. Поэтому пока в основном на уровне исследований вложения идут. Взять производителей микроконтроллеров, они взяли выпустили чип со стандартной архитектурой (могут не вкладываться в компилятор), написали драйвера для переферии и все можно выпускать, есть уже куча rtos, ide, средств разработки, библиотк, и т.д. Разработчикам готовых устройст это выгодно, вышел дешевый чип, и можно сразу начинать производство железки, ведь и программисты готовые есть.
TargetSan
Я об этом и говорю. Требуется преодолеть гигантскую инерцию.
Labunsky
После си переходить на раст больно. Язык содержит в себе гору клевых идей, но синтаксис явно разрабатывался в первую очередь для чтения компилятором, а уже потом человеком. И вечное желание сделать его максимально не С-подобным не помогает(
torgeek
Про синтаксис – это вечная американская боль. В штатах языки патентуются и для каждого нового приходится изголятся в названиях ключевых слов и описании синтаксиса, что бы не попасть на судебный иск от разработчиков других языков. В Европе всё проще, а в России так вообще спокойно – прямой законодательный запрет на патентование языков и алгоритмов.
А можно пару примеров, что в синтаксическом новоязе Rust так сильно причиняет боль?
Labunsky
Всякие си с плюсами и даже корпоративной джавой уживаются как-то, хотя я не эксперт в этих вопросах
Все перечислять не буду, можно на примере самых основных. Для обозначения переменной нужно два ключевых слова
let mut
, аналогично его должны иметь модифицируемые параметры функций. Примитивы все имеют явную разрядность, которую приходится держать в голове (неявного каста тут нет), даже если это не нужно. Функции надо помечать ключевым словом, при этом все равно явно задавая возвращаемый тип. Каждыйmatch
(здешнийswitch
) должен обрабатывать все возможные области значений, необходимо таскать с собой пустую строку дефолта_ => {}
. При создании лямбд у разработчиков сломались клавиши скобок:let closure = |i: i32| -> i32 { i + 1 };
. Возвращение значений из функций может быть явным и не- (просто последнее выражение без;
), но выражения уже не умеют вreturn
. Из-за этого, кстати, код труднее не писать, но читать — без цветной пометки эти строчки на раз пропускаются, либо вводят в смущение. И, да, выражения теперь возвращают значения, поэтому в чужом коде можно ожидать конструкций из серии:Это все только поверхостные мелочи. Но при каждом переходе между ним и другим языком бросаются в глаза. Что хуже, вместе выражаются в очень загруженный код (примеры есть тут в комментариях), в котором даже с умным парсером и подсветкой (они никак не подскажут значения
x
в коде выше, потому что тот не участвует в выражениях) без поллитры не всегда разобратьсяRyppka
Единственное, с чем частично соглашусь — неявный возврат. А все остальное — дело привычки или вкусовщина. По мне так нормально, если не нравится — идем в другой общепит.
Labunsky
Понятное дело, что дело привычки, больше раздражают причины для всего этого. Точнее, их отсутствие. Ничто не мешало сделать уже похожим на существующее без конфликтов в грамматике, но ведь нет
PsyHaSTe
Потому что портить язык вредными конструкциями только чтобы сделать его более знакомым тем, кто по этим граблям походил — плохое занятие. http://www.informit.com/articles/article.aspx?p=2425867 здесь неплохо раскзаано, почему и неявные касты плохо, и тип впереди функции, и многое-многое другое.
Labunsky
Ох уж эти глупые доктора наук Ритчи и Керниган, а потом еще и Страуструпы всякие, нагородили таких вредные конструкций, что до сих пор разгребаем, но не разгребем
Конечно плохо. В идеале, программист должен иметь лишь одну кнопку, но нажатию которой будет писаться рабочий код — вот она, мечта любого энтерпрайза
PsyHaSTe
А что, было бы плохо?
PsyHaSTe
Неправда, достаточно
let
Да, помнить, что int на этой машине 2 байта, а на этой 4 намного удобнее. Или внезапно из сишки типа int32_t пропали.
Какие альтернативы предлагает? Очень надеюсь, не писать тип функции впереди?
Действительно, какая глупость.
Вопрос привычки
Ваша претензия по сути в том, что тут "не как в си". И слава богу.
Labunsky
Это будет не переменная, потому что ее нельзя будет переменить)
Они существуют параллельно со встроенными типами данных для задач, в которых разрядность нужна явно (например, для сериализации). В остальных случаях рекомендуется использовать обычные типы данных, так как компилятор с их помощью будет генерировать более эффективный и независимый от платформы код
Про лямбды — дело в
| |
. И да, если язык позиционируется как замена, то он должен обеспечивать простой переход, а не изобретать велосипеды на каждом углуPsyHaSTe
Её и не надо менять в общем случае.
Так он генерирует как раз зависимый код.
Упростили парсер себе таким образом. В чем проблема-то?
Labunsky
Это звучит очень странно, учитывая, что свойство буквально содержится в корне слова
Неправильно выразился, сам код при написании будет меньше зависеть от платформы: какого бы размера int не был, он всегда будет целочисленным и знаковым, знания чего нам часто вполне достаточно
BlessMaster
Это не переменные, это — биндинги. В большинстве случаев переменные не нужны. Поэтому и
let mut
, чтобы ленивые люди предпочитали не использовать мутабельность там, где она не нужна.К слову, в Rust вплоне можно перекрывать старое значение с тем же именем:
let x = x + 1
. Кроме того время жизни биндингов ограничено блоками, где они объявлены. И это тоже позволяет часто обходиться без мутабельности.Labunsky
Ну так и я о том же говорю. Но на практике выражается в многословность
TargetSan
Наконец-то с первого взгляда видно, что это переменная. Иммутабельность по умолчанию я считаю скорее плюсом.
Это такой же байндинг. Было бы лучше иметь несколько разных правил?
Единственное, что может быть немного неудобно — отсутствие неяного апкаста к более ёмкого типа. Хотя — вам не хватает неявного апкаста bool->int и неявного подсчёта хеша так, как вы не ожидали? Да, эта проблема встретилась мне в С++. Но ноги растут из С. По поводу явной разрядности — вы никогда не портировали программу с win16 на win32? С резким разрастанием размера int?
default int сами же авторы С посчитали очень плохой идеей. unit return же указывать необязательно. Про явное ключевое слово fn — вы соскучились по most vexing parse rule? Я — нет.
И это прекрасно, я считаю.
Здесь уже вкусовщина. Мне такой синтаксис кажется вполне имеющим право на жизнь.
Expression-based language. Особенность, которую надо знать.
Вы вполне можете использовать блок как часть выражения. И делать из него return.
Неявный return да, может быть неудобен или непривычен. В целом же после небольшой практики и благодаря гораздо более мощному тайпчекеру перестаёт быть проблемой.
В целом же, как человеку, пишущему на С++, мне ваши претензии кажутся сводящимися к "Этот язык не похож на привычный мне С". То, что множество языков скопировало этот синтаксис, не означает, что он лучший. Просто он более распространённый и привычный.
Labunsky
Да ну я это не скрываю, первый же комментарий содержит аналогичную подстроку:
PsyHaSTe
Тоже хотел уточнить, что не так? Обычный МЛ-подобный синтаксис. Собственно из синтаксиса в си нормальные только скобочки, все остальное фигово — объявление функциональных аргументов, type first, вот это все.
snuk182
Попробуйте осилить синтаксис Nim — Rust после него покажется прогулкой в лесу под пение птиц :)
amarao
Аргумент про управление памятью — практически главный. Второй — это фиксированное ABI, с которым можно быть совместимым. (Для сравнения, с C++ ABI можно быть совместимым только при компиляторе той же версии, и удачном положении луны на небе).
Однако, никто не упомянул слово Rust, который:
а) Умеет ручное управление памятью и может генерировать код без рантайма (читай, эмбедд и ОС)
б) умеет быть совместимым в обе стороны с С-ABI.
И мне странно, потому что с точки зрения безопасности, разница между С и Rust, как между ездой на крыше синкансена и в его салоне.
abondarev Автор
наверное соглашусь, хотя сам Rust не использовал.
Но если упоминать
то в чем же его преимущество? То есть будут дыры в Сишном коде, а хочется чтобы было всегда и везде!
С другой стороны, это конечно уменьшение мест с потенциальными проблемами, но если посмотреть на это с той стороны, что существует уже много написаного и отлаженного кода и проверенных временем программ, то можно сказать, что это тоже путь к безопасности. Вы не согласны?
amarao
Ох, вы открываете гигантский топик.
Совместимость с С-ABI означает, что на Rust можно написать so'шку (с которой потом может слинковаться бинарь на том же Rust). Rust как и C++ не имеет стабильного ABI, так что использование foreign interface (aka C-FFI) отличное решение.
На самом деле, никто не уверен, что на Rust можно написать конкурентную ОС общего назначения. В силу более строгой типизации Rust, не всё, что может быть написано на Си, может быть написано на Rust. В этот список в основном попадают плохие вещи (undefined behaviour), но под общую гребёнку попадают и потенциально полезные (конкурентное изменение общего состояния). Удастся ли из оставшегося сделать ОС — вопрос открытый.
ЗЫ В Раст есть unsafe (ключевое слово), которое отключает несколько важных проверок, так что наделать багов Си-уровня можно и в Rust. Другое дело, что в нормальной программе unsafe секции маленькие, а в С — начинаются с первого #include и заканчиваются EOF в конце.
А вот почему Rust'овое управление памятью чертовски безопасное (более безопасное, чем даже в языках с garbage collector'ом), быстро не описать. Это как раз его фирменная фишка — lifetimes, ownership/borrow, и, опять же, безумно строгая типизация уровня haskell.
DSolodukhin
Unsafe в Rust по факту дает только одну новую возможность — разыменовывание сырых указателей (возможность вызывать код, написанный на С мы здесь не рассматриваем). При этом у вас остаются проверки связанные с заимствованием и владением, с конкурентным доступом к данным и пр. Поэтому наделать кровавого фарша как в С, с помощью unsafe сложно, разве что специально поставить перед собой такую задачу.
humbug
Вообще нет. unsafe так же даёт возможность работы с глобальными статическими переменными, реализовать unsafe impl (Sync). Так что им можно натворить кровавых вещей очень просто. И такие баги уже находили, хотя они жили в стд несколько лет, «проверенные временем».
DSolodukhin
В целом, я с вами согласен, но я бы не назвал приведенные вами примеры как «очень просто», это я как раз отношу к категории «специально поставить перед собой такую задачу».
Изменяемые статические переменные — это вообще антипаттерн, если уж так хочется, стоит хорошо подумать, действительно ли оно вам надо, и если надо, то может быть стоит воспользоваться безопасными решениями? Тот же lazy_static + Mutex или RwLock. И unsafe не нужен и безопасный конкурентный доступ.
snuk182
Адресная арифметика тоже подпадает под unsafe. Каст нетолстых указателей (например, для реализации си-подобного наследования) туда же.
mayorovp
А зачем нужны адресная арифметика и си-подобное наследование?
snuk182
Арифметика — для ускорения алгоритмов. Все же быстрее срезать угол, если знаешь расположение данных, и можно сказать компилятору смещение, вместо честного поиска по указателям.
Наследование — неотъемлемая часть графических интерфейсов, к сожалению.
mayorovp
Я спрашивал не про наследование вообще, а про си-подобное наследование.
snuk182
А разницы никакой. Это всего лишь единственно доступная в Rust на данный момент возможность реализации наследования — начинать структуры-наследники с общей структуры-базы.
mayorovp
Вот только канонический способ не использует приведение указателей, а дублирует требующие наследования методы:
Получается несколько многословно, но рано или поздно эту проблему решат.
snuk182
При наличии крупного функционала родителя эта многословность мгновенно встает огромной проблемой. Есть RFC на эту тему, но с ним проблем больше, чем без него.
mayorovp
Это какой-то не тот RFC. Правильное решение тут — реализация чего-то вроде derive для произвольных трейтов.
Пока же можно какой-нибудь Into вместо наследования использовать.
snuk182
Derive уже есть очень давно, но это точечное решение, которое надо руками подгонять под каждый отдельный типаж. Красиво такая штука реализована в Go — вложенные структуры без имен переносят сигнатуры своих публичных методов на внешнюю структуру. Этакий декоратор на стероидах. Rust такое наверное не светит — очень уж неявно.
Заменить наследование для задач именно наследования, а не подстановки — нечем. Существующие решения подразумевают копипаст, что не лезет ни в какие ворота. Можно бы исхитриться и реализовывать базовый типаж для реализаций типажа-наследника, чтоб не копипастить, но увы, orphan rules прилетают и бьют по попе. Да и специализация до ума не доведена.
Ryppka
А как без нее решать низкоуровневые задачи? Вот прекрасная статья на тему: www.cs.kent.ac.uk/people/staff/srk21/research/papers/kell17some-preprint.pdf
abondarev Автор
ну что же, тема то действительно интересная :)
скорее всего единственно возможное. Поскольку нужно предоставить возможность использовать существующее ПО. Пока вижу что индустрия так устроена, что все хотят использовать свои наработки. Вон в банках до сих пор еще всякие VAX архитектуры и майнфреймы s/360 используют, плюс язык COBOL.
да я как раз про unsafe, и согласен что уменьшение проблемных мест это хорошо.
На счет ОС общего назначения, ну можно начать с ОС специального назначения, мы например хотим какой то модуль или драйвер написать. Но вот с драйверами как раз и показательная ситуация, сейчас определяющим является поддержка аппаратуры. В свое время мы даже хотели сделать совместимость с драйверами linux (но решили что частичной совместимости достаточно) и добавили других фишек, типа использование bsp от производителя. это я к тому, что без использования драйверов написанных на Си, вряд ли получиться что то используемое. А если не используемое, то опять канет в лету.
Вот прямо очень был бы благодарен, если пусть не быстро, а в отдельной статье, но Вы описали «почему». Сами занимаемся управлением памяти в проекте, и всякие тонкости очень интересны! :)
mayorovp
Могу объяснить в двух словах.
Во-первых, Rust следит за ссылками на объекты, как статически (по умолчанию), так и динамически (примитив RefCell), а потому всегда знает, эксклюзивно вы владеете объектом, или же к нему имеет доступ кто-то еще. И от этого знания зависит какие операции над объектом можно делать.
Во-вторых, в Rust переменная уничтожается после переноса, что вместе с прошлым пунктом исключает класс ошибок use after free. Причем исключает статически.
Сравните:
abondarev Автор
Спасибо.
Правда я имел в виду как это реализовано.
То есть если идет статический анализ, то как он вообще может отследить путь если ссылка отдается во вне, и статический анализ достаточно долгая штука.
mayorovp
Этот анализ никогда не выходит за пределы одной функции. Система типов Rust позволяет выразить утверждение, что переменная foo проживет, по крайней мере, столько же сколько и переменная bar. И если такого отношения между "внёй" и переменной нет — то ссылку на переменную передавать "во вню" нельзя.
abondarev Автор
Понятно, спасибо!
DSolodukhin
У каждой ссылки в Rust есть lifetime, т.е. время жизни. Компилятор проверяет, что время жизни ссылки не превышает время жизни переменной, на которую она ссылается. Вот очень простой пример кода, который в Rust не скомпилируется:
Мы пытаемся вернуть ссылку на переменную, которая будет уничтожена при выходе из функции. Это ошибка.
Вообще тема с ссылками и временами жизни одна из самых трудных для новичков в Rust, потому что в других распространенных языках такого нет и не получается сразу привыкнуть.
abondarev Автор
Ну этот пример конечно понятен, но блин, если кто то выделил переменную на стеке а возвращает указатель, то ну не знаю как его назвать, но точно не системным программистом.
За пример спасибо!
DSolodukhin
Ну это очень простой пример, исключительно показать концепцию.
Но эта концепция работает везде, например, если вы хотите сохранить в структуре ссылку, то должны гарантировать, что ваша структура не будет существовать дольше, чем переменная, на которую вы взяли ссылку.
Так же ссылки по умолчанию иммутабельные, если вы хотите изменять данные по ссылке, вам понадобится явно это указать &mut data. Rust позволяет создать много иммутабельных ссылок и только одну мутабельную, если уже есть иммутабельная ссылка, то создать мутабельную нельзя — будет ошибка компиляции, и наоборот.
По расту есть хорошая книга, по крайней мере лучше чем официальный растбук — Блэнди Дж., Орендорф Дж. — Программирование на языке Rust. Там относительно неплохо объясняется работа со ссылками, концепции владения и заимствования.
abondarev Автор
По сути, то за чем следит программист и приличные практики программирования, вынесены в синтаксис языка?
То есть конечно должны быть соглашения о том кто выделяет кто освобождает и кто может модифицировать данные по ссылке. Они всегда есть, если нет то проект быстро развалится!
Halt
abondarev Автор
В общем, нужно попробовать на чем нибудь небольшом, чтобы проникнуться идеями.
Halt
Разумеется. Наброшу вам еще немного полезных ссылок по теме:
Halt
Проблема не в передаче ссылки как таковой, а в отсутствии контроля за ее временем жизни. Когда вы передаете параметры в функцию они тоже вполне могут лежать на стеке и использоваться по указателю.
Веселье может начаться в случае если кто-то внутри дерева вызовов уже забыл о том что вот этот указатель пришел со стека а не из кучи и утекать его нельзя.
В классических языках ответственность лежит на программисте. Rust это контролирует явно, как и протокол совместного доступа к подобным ресурсам. Что в однопоточном, что в многопоточном варианте.
Таким образом ситуации вроде use after free, double free, инвалидации итератора или состояния гонок оказываются невозможными.
abondarev Автор
Да. Написал об этом выше в комментарии
amarao
Ситуация становится чуть-чуть сложнее, когда вы хотите передать указатель на переменную на стеке в соседний тред. В нормальном режиме в Rust это сделать нельзя (потому что не ясно сколько стек проживёт относительно треда), но библиотеках Rust'а есть такая конструкция, которая гарантирует компилятору, что треды закончатся до завершения текущей функции, так что можно безопасно передавать ссылки на свой стек в треды.
Вот эта штука, когда компилятор всё время озабочен тем, кто владеет, кто не владеет, кто когда завершается — это офигенно. Оно ловит огромное количество багов вокруг mutable/shared, а "обходные пути" вокруг ругани компиляторов обычно оказываются очень правильными архитектурными решениями.
PsyHaSTe
Ну вот вам более реалистичный пример
Тут та же история, но она уже припрятана под кучкой shared_ptr, которые правда не помогают.
Если же его наивно перенести на раст
То получите ошибку
Весь смысл в том, чтобы получать ошибку в таком случае, а не философствовать на тему "может ли человек считать себя программистом. если допускает подобные ошибки".
Причем что самое интересно, компилято раста поймет, что значение еще живет в месте первого вызов принтлна, а во втором уже нет. Поэтому ошибка будет только при попытке скомпилировать последнюю строчку.
mayorovp
Примеры тут не совсем эквивалентны, в плюсовом коде ошибка не в main, а в функции f.
PsyHaSTe
Я не переписывал 1в1, потому что это невозможно, а пытался догадаться, что хотел программист этим кодом сделать. Я предположил, что он хотел воспользовать x по ссылке в лямбде, что и изобразил в расте.
hhba
Пытаюсь понять, какой вариант выглядит более вырвиглазно — плюсовый или растовый…
PsyHaSTe
А что вырвиглазного в растовом примере? Единственный генерик-параметр? Если очень неприятно, можно воспользоваться анонимным лайфтаймом
hhba
Поскольку я с этим языком не знаком в достаточной мере, то отчасти моя реакция вызвана банальным непониманием написанного. Но мне кажется также, что синтаксис у языка объективно вырвиглазный. Как и у шаблонизированного кода на плюсах с использованием стандартной библиотеки. Хотя с Растом все даже хуже. Не зная ничего о шаблонах С++, можно тем не менее по наитию понять, что же там написано. Глядя же на первый вариант растового кода (с генериком) я вообще не понимаю «что хотел сказать автор». Да, еще раз, дело в незнании языка, но кажется, что это положение дел весьма показательно.
PsyHaSTe
Нет, просто тут написано тупо больше, чем обычно пишут. Если вы видите кода в 2 раза больше, то и читать его в целом в 2 раза труднее.
Давайте разберем:
Иными словами, мы говорим "я хочу вернуть лямбду, которой можно пользоваться все время, пока жива переменная
x
". Какие вещи тут непонятны. impl? Это просто экзистенциальный тип. В C#/Java за этим обычно скрывается просто бокс с интерфейсом, в хрусте компилятор подставит конкретный тип. Поэтому в расте можно вернуть какую-нибудь анонимную структуру, а в том же C# анонимный класс вернуть не получится, потому что его тип записать нельзя.Не знаю, как по мне все достаточно просто. Причем я не плюсовик ни разу, посмотрите мои статьи, я C# разраб. И мне все это достаточно очевидно. Скажите, что конкретно в этой записи вас смущает, я просто серьезно не могу понять, что тут сложного, не считая б0льшего объема информации.
Просто если попробуете все то же записать при помощи той же джавы, у вас кода будете еще больше. Ну то есть как-то типа
стало ли понятнее?
hhba
Во-первых спасибо за объяснения!
Проблема в том, что смущает буквально все. Что-то конкретное трудно назвать.
Вот в этом «не считая» кроется основная проблема — информации много, но понимания она не добавляет.
И очень хорошо — кода больше, и он внезапно понятнее! То есть в Джаве введена разумная избыточность. И хотя я не понимаю, что в этом коде собственно происходит, но его синтаксис хотя бы понятен.
PsyHaSTe
Тогда это просто вопрос привычки. Ну примерно как после паскаля с begin/end перейти на Си.
Могу посоветовать смотреть на разные языки. Обычно классика считается один си-подобный императивный, один логический, один функциональный, ну и sql. Нужно понимать, что привычный синтаксис не значит удобный. И соовтетственно
Нет, просто вы привыкли её видеть.
Выпишите просто что вас смущает. Ведь у каждого дизайн решения языка есть своя причина. Например, эрик липперт в статье про "топ 10 фич сишарпа о которых мы жалеем" в один из топа списка поставил "зря мы взяли из сишки то, что тип пишется впереди имени функции и переменных".
hhba
Да ну нет же! То есть конечно фактор привычки нельзя игнорировать, но он не ключевой.
Насчет Паскаля — перейдя с него на Си я очень порадовался, что вместо begin/end появились брекеты. Их конечно тоже надо уметь готовить, но они гораздо понятнее. И вообще я очень быстро «отошел» от паскалевских заморочек, именно потому, что Си понятнее.
Насчет «Си-подобных императивных». Во-первых, кое-кто говорит, что Раст как раз из таких — и чем же они похожи с Си? Во-вторых, кое-кто говорит, что С++ из таких — но при использовании некоторых приемов программирования плюсовый код превращается в
кашучто-то совершенно не похожее на Си. То есть этот термин (Си-подобность) какой-то неоднозначный. А если мы редуцируем вашу фразу до «императивный» (без указания референса), то ведь это не о синтаксисе получается…Насчет SQL — отличный пример, я написал в свое время немало запросов. И мне нравится лаконичность и внятность этого языка. Я сразу начал понимать, что и как там делается, без длительных объяснений. То есть внезапно беда не в императивном клинче моего мозга.
Да конечно, я на Джаве писал сто лет назад, и это была другая Джава.
Угу, часто об этом говорят, хотя разумных аргументов лично я не слышал. Слышал только разные инсинуации.
Проще сказать, что я смог понять сам (если игнорировать ваши разъяснения). А именно — имею догадку, что «i32» как-то соотносится с int32_t, но это не точно. Еще есть смутное подозрение, что "&" имеет отношение к взятию адреса (то есть это ссылка на что-то, возможно это ref/out), но и это не точно. Вот и все.
PsyHaSTe
Просто язык достаточно бедный. Весь состоит из десятка ключевых слов. Ни обобщений, ничего нет. Предметная область достаточно простая, вот и вся история. Достань, пофильтруй, заапдейть.
Ну вот вам аргументы, почитайте.
Ну все так и есть. Возьмем еще раз
Объявляем функцию
f
с параметромx
типассылка на 32битное знаковое целое
, которая возвращает тип, реализующий интерфейс() -> i32
, то есть лямбду, возвращающую целое 32битное знаковое целое, и имеющее время жизни такое же, как входной аргумент.Еще раз, туп тупо больше информации записано. Если бы на джаве пришлось бы так же писать, на ней никто бы не писал. Поэтому спринг и ненавидят, где приходится аннотациями обмазываться с ног до головы. А было бы на порядок хуже.
hhba
Само собой, но вы ведь сами привели его в пример.
Возьмите какой-нибудь другой бедный язык, будет ли он так же понятен?
Наверное сложность понимания обусловлена также и сложностью примера. Потому что из текстового описания у меня например формируется вопрос «а зачем это нужно?» )))
BlessMaster
На самом деле здесь больше информации с вполне конкретной целью: мы сообщаем компилятору, "что мы на самом деле имеем в виду". Впоследствии компилятор забирает у разработчиков массу головной боли и ручной работы, проверяя за них "всё ли согласованно написано в программе".
На примере в несколько строчек эта полезность не так заметна и выглядит несколько странно. В крупном же и важном проекте, над которым работает немаленькая команда — можно только молиться на компилятор, который избавляет тебя от сегфолтов и прочих очень неприятных недоразумений, которые можно часами ловить в отладчике, или вообще до часа X не догадываться об их существовании.
Потому что, когда такой час X "пробивает", обычно остаётся только устраивать сеанс спиритизма в три часа ночи, чтобы понять, ГДЕ этот чёртов косяк, из-за которого всё внезапно начало падать или почему остатки на счетах превратились в тыкву, и как это побыстрее исправить, ибо бизнес несёт убытки.
Это, конечно, не серебряная пуля и не избавляет от всех багов вообще, но за то, от чего избавляет — это не такая уж и высокая цена писать всё чуть более многословно. Тем более, разработчики языка постарались насколько это возможно многословность нивелировать синтаксическим сахаром.
Я бы даже добавил, что когда получается слишком раздутый код — в Rust это примета того, что "что-то пошло не так" и используется не лучшее архитектурное решение. Это особенно актуально для новичков, которые пытаются натягивать на Rust привычный стиль написания программ из других языков.
hhba
Не, ну мотиваторы мне известны, и я их не отрицаю. Просто мне кажется, что все то же можно было сделать более внятным образом. Не короче по количеству текста, возможно даже длиннее, но понятнее.
vvmtutby
В Modula-2 (1979), ADA ( стандарт и первый сертифицированный компилятор — 1983) и Oberon «детская болезнь» Алгола-60 решена на уровне синтаксиса языка.
В экосистеме Си — внесли в Misra C указание для носителей «естественного интеллекта».
snuk182
Популярность Котлина доказывает обратное.
hhba
Не могу ничего сказать про Котлин, да и про Джаву мало что знаю (изучал в институте сто лет назад), так что я комментировал конкретный пример, и только.
KanuTaH
В Rust все сделано банально "вовне" ссылку передать нельзя :) Period.
abondarev Автор
То есть, для системных нужд его без unsafe не получится использовать?
KanuTaH
Ну на низком уровне, где идёт работа с ресурсами (выделение, уничтожение) — скорее всего, да.
Halt
Я не знаю что имел в виду KanuTaH коворя о «вовне», но unsafe совершенно ортогонален всему этому. Основная идея — разделение кода на безопасные и потенциально-опасные части. Если интерфейс модулей спроектирован верно, и инварианты контролируются, то все должно быть нормально.
В системных задачах, как правило, без unsafe не обойтись, но это не значит, что весь код будет им обмазан с ног до головы.
Например, в операционной системе Redox, написаной на Rust, unsafe встерчается только в строго ограниченных местах, тогда как бизнес логика, будь то менеджер страниц или диспетчер многозадачности, описывается на безопасном подмножестве.
Halt
Ну и выше уже писали, что unsafe не отключает проверки, он разрешает дополнительные потенциально опасные операции (и это важно). Что именно происходит хорошо описано тут: You can’t “turn off the borrow checker” in Rust.
abondarev Автор
спасибо!
Halt
Всегда пожалуйста. Если что, с вопросами можете обращаться в личку.
P.S.: Про разработку embedded категорически рекомендую блог человека, стоящего на острие прогресса Rust в этой области. По сути он и есть прогресс: blog.japaric.io
Там же вы можете увидеть примеры фантастического API который позволяет статически на этапе компиляции контролировать использование ресурсов и не допускать типичных проблем с памятью и ресурсами. Я думаю подобные вещи гораздо лучше помогут вам оценить преимущества Rust нежели стандартные статьи, ориентированные на широкую публику.
abondarev Автор
Хорошо, спасибо. Если что обратимся :)
Блог прикольный!
mayorovp
Но ведь в Rust есть все нужные примитивы для этой цели...
mayorovp
Вообще-то С++ так тоже умеет,
extern "C"
вроде же как раз для этого сделан...kovserg
Рещил как-то попробывать rust — впечатление смешанные.
1. скачать инсталятор для windows — квест
2. скачал инсталятор для 32bit windows запустил и он бодро установил 64bit rust вместо 32bit
3. обнаружил в директории .cargo/bin файлы идентичны по 5.7Мб которые по сути являются ссылками. ( 67мб просто 12 ссылок )
4. побывал специально на слабой машине — rust очень тормозной в сравнении с другими тормознее только cuda-вский компилятор.
Весь такой системный язык так невнимательно относится к системе.
Выглядело так что сейчас этого синкансена придётся тащить на буксире.
mayorovp
Так это же и правда ссылки: на диске файл хранится всего в одном экземпляре, просто у него есть 12 разных имен.
mayorovp
amarao
Ну, формально, вам надо просто поставить WSL, а там-то с Rust всё просто супер. Включая кросс-компиляцию под винды.
Ryppka
rustup Вам в помощь, и ставьте все, для чего компоновщик есть. Хотя на Windows вроде требуется полный компилятор: или msvc, или mingw32-w64 (он и 32-битный бывает).
TargetSan
Ставим Visual Studio Build Tools и имеем всё недостающее. На страничке rustup это вроде было описано.
snuk182
Чем-то вы страшным занимаетесь, будто вам Рабинович напел Карузо.
Под винду скачивается единственный экзешник, который даже не требует админских прав. Запускается, далее, далее, готово. Для пользователей без опционально требуемой Visual Studio 2017 (для сишных биндов, если будете использовать) можно вместо одного из Далее указать "хочу gnu вместо msvc", поставится сразу легкая версия mingw. В итоге все компактно сложено в
~/.cargo
и~/.rustup
, запускается отовсюду, использует все ядра и потоки по умолчанию (может быть потому и тормоза на слабой машине).ripandtear
Занимаюсь программированием различного Embedded'a на протяжении ~7 лет, скромное мнение:
— Для решения проблем с надежностью есть стандарт MISRA C. Может быть есть и другие, но с ними я не знаком.
— Очень много legacy и того что мы используем каждый день, написано на С. Да все и так я думаю в курсе. Я работал и работаю со многими закрытыми и открытыми DSP-процессорами и ядрами, практически везде используется С89 или С99 для написания к ним прикладных программ. Все кастомные тулчейны и т.п. — это все для С.
— Я бы рад перейти например на тот же Rust. Но на него не переходят в своих тулчейнах Analog Devices, Qualcomm, CEVA, и др. компании. Т.е. как уже было выше отмечено, в первую очередь поддержка должна идти от них.
— Продакшен конечно разный бывает, но лично у нас смотреть в сторону Rust'a начнут, когда появятся нормальные рабочие инструменты от тех же производителей железа, с которыми мы работаем.
abondarev Автор
Все правильно, это однин из главных сдерживающих факторов.
Разработка собстенных средств разработки (как например предлагали на конференции компилятор языка Си для ARM) естественно будет содержать ошибки. И вот как с этим быть непонятно, но когда индустрия дозреет, и будет несколько отлаженных и доступных компиляторов, вот тогда…
Halt
Маловероятен, но в принципе возможен и обратный вариант. Например если, условно, www.tockos.org или Embox станут популярными настолько, что вендоры будут видеть в их поддержке конкурентное преимущество и уже сами озаботятся совместимостью тулчейна.
С учетом гарантий, которые дает Rust, мне не кажется это таким уж невероятным, тем более, что существует инициатива по сертификации Rust для критических систем.
oam2oam
Если говорить о надежности программ и скорости разработки, то почему не рассматривается язык Ада? Он к тому же и позиционировался как язык для встроенных систем. Ну и «выстрелить себе в ногу» на нем о-очень сложно…
К тому же на нем отлично пишется для микроконтроллеров. Ну и нет абсолютно никакого зоопарка со стандартами и компиляторами. К слову сказать, gcc поддерживает не так много языков, но среди них — Ада.
А так, кажется порой, что абсолютно все возможности современных языков сначала (очень давно) были в Аде, а потом уже в пошли в массы. К тому же, очень-очень мало языков поддерживают параллельное выполнение на уровне самого языка (не библиотек или там классов), а это сейчас все более актуально.
Да что говорить — все же программирование когда-то, похоже, свернуло не туда и не стали популярны Ада, Пролог…
abondarev Автор
Язык Ада безусловно обсуждался в рамках данной дискуссии и в рамках обсуждения языка Оберон. Кстати, в кулуарах Дмитрий Дагаев на вопрос об Ада сказал, что не хочет использовать его на АЭС (а использовал Оберон) поскольку сейчас существует только один сертифицированный компилятор для подобных систем и как Вы понимаете он не у нас разрабатывается и его просто не продают.
Еще возникает вопрос с кросс-платформенностью, но это по идее должен решать gcc.
Siemargl
Как будто существует сертифицированный компилятор Оберона…
Там вообще содомия творится — стандартного компилятора нет, а есть миллион самодельных компиляторов и у каждого _свои_ расширения (потому что куцый функционал стандарта — даже без базовых библиотек), и неоднозначности толкования.
Ада — это цельный продукт, но она не сильно то проще С++ %-) И ее реализации вполне могут быть неполными — без менеджера памяти, например.
vvmtutby
A) Т.к. несколько причастен к «постам и вопросам», приведу сокращённый ответ ( хотя бы, как повод к поиску первоисточника):
Дмитрий Дагаев, «отвечая на посты и вопросы»:
Siemargl
Active Oberon выглядит неплохо, но компилятор единственный под свою частную песочницу. Существенных проблем (кроме того что рантайм песочницы WinAOS/LinAOS имеет качество некоммерческого студенческого проекта) там отсутствие проверок переполнения/качества вычислений и контроль ошибок только кодами возврата. Принципиальной выгоды перед промышленным стандартом IEC 61131-3 ST я не вижу никакой, скорее наоборот.
Говорить, что исключаем опенсорсный! компилятор АДЫ из рассмотрения по вышеуказанной причине, имея для АО еще худшую ситуацию — это прямой и явный зашквар (заинтересованное участие в «тендере» выбора решений).
abondarev Автор
позволю привести немного переписки от уже упомянутого Дмитрия Дагаева:
по поводу АДЫ
То есть, от АДЫ не отказывались, просто на сегодняшний день в РосАтоме проблемы с его использованием, чисто бюрократические. Надеюсь в нашей стране тоже научатся работать с идеями открытого кода.
По поводу компиляторов и рантаймов:
То есть идея в том что поскольку очень простой синтаксис, это можно сделать силами небольшой команды.
Лично я придерживаюсь мнения, что это работает, но только до определенного момента. Когда технология начинает реально использоваться, причем независимыми разработчиками в разных (не единичных проектах), этот подход перестает работать. И тогда одним из вариантов является опять же opensource.
LLVM (да и С тоже) как раз в сторону открытого подхода
Fenzales
Тео де Раадт из OpenBSD в своё время разразился хорошим письмом на эту тему:
tl;dr Rust (или любой другой язык) не вытеснил C, потому что никто не пишет на Rust сопоставимые альтернативы.abondarev Автор
Для некоторых вещей скорость компиляции не так критична. Хотя конечно это важно для массового испольнования.
Проблема с функциональными языками еще и в том, что если у вас ошибка в логике, то никакой язык вас не спасет.
Fenzales
Revertis
Кажется, замену grep'у уже пишут.
snuk182
Не просто кажется, но уже давно есть и даже дистрибьютится.
Revertis
А, ну вот. Круто ведь!
Halt
Я бы добавил еще что он давно уже используется по умолчанию для поиска по проектам в VSCode.
Fenzales
В *BSD не
линуксовыйGNU/grep используется, по-моему.zloe_morkoffko
abondarev Автор
Ну включать выключать настраивать модули, дело не хитрое, в linux ядре можно спокойно вызвать менюшку написанную на qt, и там прекрасно пощелкать мышкой. Тут все гораздо серьезнее. если я правильно понял то это близко к filter graph.
А WxWorks 653 имеет описание в xml формате, и там действительно много чего можно настраивать. Но даже у нас в Embox, наверное больше возможностей по конфигурации системы.
MSC6502
Вся история IT-индустрии показывает, что по какому-то иррациональному, никому не ведомому признаку программистское сообщество выбирает самый сложный, самый опасный, самый трудный и рандомнобихевористческий инструмент для своих разработок. Примеров есть некоторое количество (С++, js, java, python ). Самое печальное, что эти инструменты занимают лидирующие позиции в рейтинге ЯП. Детально знать и держать в голове тысячу страниц описания с++ не может ни один человек в мире. А уж знать и предвидеть результаты интерференционных явлений, возникающих при использовании десятков разных библиотек, наверное под силу одному-двум суперпрограммистам из близлежащих галактик. В то же время тщательно разработанные инструменты объявляются немеэйнстримными, устаревшими, несовременными и проч. Это поведение коллективного разума IT сообщества невозможно понять. Появляются десятки новых языков уровня КП 3 курса с комьюнити в пару тысяч человек. Это как если бы на заводе инженер в целях самовыражения решил бы в новой машине использовать новые болты с резьбой М13.726 или 4.735. Думаю, что на следующий же день он искал бы новое место работы. Информационные технологии занимают в жизни планеты всё большее место. Результаты использования небезопасных инструментов и технологий мы все знаем. Это постоянно обнаруживаемые уязвимости разного уровня опасности в ОС, приводящие у утечкам конфиденциальных данных, потерям финансовых средств. Методология разработки программного обеспечения, равно как и языков программирования, должны уже давно стать глобальными, наднациональными задачами. Пора уже отбросить узкокорпоративные шоры и погоню за кратковременной выгодой. Основа основ мировой IT структуры — операционные системы и средства разработки должны быть общедоступны и бесплатны. Причем эти основы должны быть сконструированы хоты бы с такой степенью тщательности, как Ада. Да, уже конкретные прикладные пакеты могут быть платными. Но некоторая тщательно проработанная общедоступная база должны быть. Потому что, чем дальше, тем больше появляется несовместимых стандартов и решений, в итоге на решение проблем совместимости уходят громадные ресурсы, которые могли бы быть использованы более продуктивно. (Если что, я сторонник паскале-подобных языков — Ада, Delphi, Оберон, Seed7).
abondarev Автор
Ну так opensource есть, Linux gcc gdb?
Ну есть другой подход делать надежные программы, «Собор и базар»
Дело вкуса, я уж точно не противник этих языков.
Можно долго холиварить по поводу какой язык лучше. Но мне кажется, что время покажет для каких задач подходит тот или иной язык. Наприме, java задумывался как язык для всех типов платформ, кросплатформенный. В итоге основное серверная часть была как раз на нем написана, наверное для этих целей он был наиболее хорош, но это же не маленькие устройства, хотя попытки постоянно были. ой забыл про Android, но например Kotlin, замечательно зашел в этом плане как замена Java. Или python, сейчас на нем делают очень много прототипов и проводят моделирование, язык лучше отвечает характеристикам для подобных задач. Есть старые языки, которые почему то ушли в прошлое, есть языки которые так и не нашли свою нишу.
В общем, я стороник opensource, а языки нужны разные для разных целей. А если Вы сторонник Оберона почему бы не присоединиться к проекту по обучению этому языку Информатика 21
taujavarob
Во-первых, «фишеровское убегание». Это вот что: самка выбирает привлекательного самца, чтобы ее дети-самцы тоже были привлекательными. При этом признак «любви к привлекательным самцам» у самки оказывается полезным — ее дочки-самки тоже унаследуют страсть к бесполезным, но прекрасным мужским чертам, в результате чего обеспечат своим сыновьям репродуктивный успех. Со временем эта система идет вразнос (почему и называется «убеганием»), то есть два признака — павлиний хвост самца и любовь к павлиньему хвосту у самки — развиваются до тех пор, пока признак мужской красоты не станет почти летальным. При этом процесс может начаться с небольшого случайного отклонения женских предпочтений, а потом наступает цепная реакция.
Вторая теория — «гандикапы» Амоца Захави. Она вот о чем: самки выбирают самцов с вредным признаком, потому что выживание таких самцов свидетельствует об их высокой приспособленности. Гены этой приспособленности унаследуют не только сыновья, но и дочери, то есть в совокупности такой выбор окажется полезен.
Вспоминая Докинза (С)
johnfound
Все выше пишут как будто производительность все еще удваивается каждые 18 месяцев.
KanuTaH
М-да, ещё когда я в институте учился, лет 20 назад, ломались копья на тему «C vs Ada/Oberon». Типа вот-вот, ещё чуть-чуть… Прошло 20 лет, а дискуссии все те же :) Ну моднявый Rust ещё появился, да. Но насчет него тоже автор статьи выше совершенно справедливо написал про «5 лет назад» :) Modern language — это, конечно, хорошо, и даже замечательно, но продакшн есть продакшн.
abondarev Автор
Не только Rust появился. Появилось много языков. На Rust как раз до сих пор еще мало пишут. Но всякие Kotlin, Go нашли свою нишу и прекрасно применяются в продакшене.
А обсуждение очень важно как раз для развития. Время само раставит все по своим местам. Пока C стандарт де факто по крайне мере для системного программирования, но может в будущем появится более лучшая альтернатива!
KanuTaH
Ну я конкретно про системное программирование имею в виду. Споры все те же, один в один (даже предлагаемые альтернативы все те же, за исключением Rust), ну и воз все там же :)
abondarev Автор
Тут согласен, Си для системного программирования пока никто не переплюнул, поэтому все и вкладываются в эту сферу и драйвера и операционки и обучение.
hhba
Один мой вузовский препод говорил следующее: «Я знал старого одного программиста, он недавно умер, так вот он часто говорил, что Си скоро умрет. Но пока это не произошло — открываем редактор и пишем...»
perfect_genius
Вывод: Си нас всех ещё переживёт.
AVI-crak
Дело в том что язык Си — очень близок с идеей предварительной компиляции. Ключевое слово — «предварительной». Проверка кода на безопасность должна быть произведена до окончательной сборки.
То-есть нужно сначала хорошо подумать, для того чтобы ваша новая функция выполняла именно то что вы задумали, и ничего более. Проблема в большом количестве необходимых действий, примитивных по своей сути — но в них можно ошибиться. Это в языках более высокого уровня в функции может быть всего одна или две математические операции — а всё остальное пространство заполняет длиннющие имена переменных. В Си не так, имена короткие — а действий много.
Ошибки которые можно допустить в таком коде — уже давно всем известны, и многие анализаторы кода их успешно находят. Проблема в том что эти анализаторы внешние. Нет такой IDE, что в режиме набора текста будет показывать ошибки, и главное — варианты их решения.
Наверное это очень сложно — распознать массив, его границу, и возможный выход за границу массива. Настолько сложно — что в данный момент нет даже попыток создания подобного плагина.
Я утверждаю, проблема безопасности Си — это полное отсутствие инструментов проверки/подсказки алгоритмов пользователя во время его набора. Когда появится поддержка — все вопросы отпадут сами собой.
KanuTaH
Даже если таких инструментов нет прямо в IDE, то это решается путем создания правильного процесса CI. Перед тем, как попасть в основную ветку, новый код должен быть в обязательном порядке и автоматически проверен всеми используемыми анализаторами и пройти все тесты. Без этого merge просто не должен проходить. А уж инструментов для решения подобных задач вагон и маленькая тележка. Но и все эти анализаторы не дают 100% гарантии отсутствия ошибок. Впрочем, расты с оберонами точно так же сами по себе таких гарантий не дают.
staticmain
Последний QtCreator на лету проводит clang анализ и прямо на проблемной строчке подсуазывакт, что не так.
lamerok
Clion вполне себе на ходу делает статический анализ кода…
AVI-crak
А ведь я проверял… QtCreator не различает в параметрах функции: числовые/символьные константы, горячие переменные, и перемененные с произвольной разрядностью. Видеть их видит, а связать поведение алгоритма с их типом не может.
Самое простое — функция принимает адрес статического массива, и адрес элемента массива для изменения/чтения.
Адрес элемента числовая/символьная константа — даже gcc видит ошибку в случае промаха, QtCreator не пытается выполнять проверку.
Адрес элемента внешняя переменная — gcc ругается, QtCreator молчит.
Адрес элемента число с произвольной разрядностью — gcc бодро занимается ускорением, иногда чего-то там пишет в отладку, QtCreator прикидывается шлангом.
abondarev Автор
ну это вообще то стиль программирования, в Си можно и с длинными именами писать, а в других языках с короткими.
Ну как уже ответили, такие механизмы есть, по крайней мере проблемы решаемые путем: применения разных компиляторов, применение статических и динамических анализаторов, CI, тестирования. Все это прилично работает для небольших программ. Другое дело, что если программа большая например ядро Linux, проанализировать все возможные утечки памяти становиться не реально. И да я ядре делают собственные инструменты анализа, которые помогают улучшать надежность программ, но это как раз не от хорошей жизни.
Вероятно проблема Си в том, что изначально речь шла о профессиональных программистах, которые хорошо знают алгоритмы, организацию ЭВМ, структуры данных и следовательно пишут программы высокого качества. То есть это был переход от ассемблера к чему то более поддерживаемому. Поэтому данный язык хорошо «прижился» в системном программировании. Подразумевается, разработчик должен осознавать, что он делает.
PsyHaSTe
Проблема безопасности в Си — что для него фундаментально невозможно написать анализатор который поймает достаточно количество багов, чтобы считать язык безопасным. Ну физически, если у вас сложение двух числе это УБ то вам никакой анализатор не поможет. Потому что если у вас 90% ложноположительных срабатываний, то по сути инструмента и нет. Не помню, где читал, но для нормальной работы инструмент должен давать меньше 5% ложноположительных срабатываний.
Язык вроде раста именно это и делает. Он запрещает вещи, которые трудно анализировать, чтобы иметь возможность это делать. Запретили иметь больше одной изменяемой ссылки — найс, можно написать на это анализатор. В си две мутабельных ссылки валидная история, и написать на это проверку не получится. А из этой проверки идет много следствий, которые в си хотелось бы иметь, но нельзя, потому что фундамента нет.
В этом плане Джон Кармак очень хорошо высказался в своем твиттере
AVI-crak
Я о том и говорю — автоматический анализ должен быть в самой IDE. Чтобы встроенная!!! (а кстати почему они все внешние?) система контроля версий не допускала сохранения заведомо ошибочного кода.
То-есть проблема не в языке, а в программном обеспечении для работы с ним.
abondarev Автор
Ну в принципе никто не мешает прикрутить все это прямо к ide, большинство поддерживает выхов сторонних утилит. Другое дело, что если на каждый чих проверять анализатором, то это занимает очень много времени, а редактировать то хочется на лету. Поэтому нормальной практикой считается, ветка в системе контролля версий, которая прогоняется по тестам, аналлизируется, ревьюится, и потом мерджиться. Сейчас программы большие, работает много народу, поэтому именно такой подход.
PsyHaSTe
Осталось только научиться определять заведомо ошибочный код с достаточной точностью, чтобы программист не отключил эту проверку. Я не вижу как для Си это решается. Там наоборот, вся философия что программист "знает что делает".
Labunsky
А в чем проблема-то? Мы же не говорим, что русский плохой, потому что в нем можно построить грамматически корректные фразы, которые при этом не несут смысла, "не работают". И уж тем более не бежим создавать новый просто из-за того, что люди страдают с выражением своих мыслей на существующем
PsyHaSTe
Если бы мы писали программы на русском, то это был бы плохой язык, да.
От него не требуется даже той толики строгости, которая требуется для ЯП.
Labunsky
Но почему? Если человек на естественном (очень гибком и прощающем) языке пишет с ошибками, то мы его ругаем, зовем неграмотным. Если же программист пишет на очень строгом языке с ошибками, о многих из которых его предупреждают любые современные редактор и компилятор, — мы ругаем язык?.. И ведь ему за это часто платят, в отличие от двоечника Пети
PsyHaSTe
Там где от речи людей зависит жизнь (например, у пилотов гражданской авиации) язык как раз очень ограничен, и неграмотное его использовании стоит иногда людям жизни, поэтому там это тоже не приветствуется.
И да, мы не решаем проблему "кто виноват", язык или программист, вопрос в том, что делать с этим. Есть факт, что люди ошибаются. Просто факт. Мы либо можем сказать "ну окей" и ловить баги в приложении, либо попытаться что-то с этим сделать. Вопросы "зачем ты написал код с багом" я считаю неконструктивными.
Labunsky
Это отличный пример, кстати, недавно как раз видел расследование аварии на взлетной полосе из-за одного пропущенного уточнения. Правда, софт для аналогичных задач все равно на языках с возможностью прострела ноги пишется
В моем представлении, надо в первую очередь поднимать квалификацию, и свою, и чужую. А то так все просто разленятся и через 20 лет будут жаловаться на слишком свободный раст)
KanuTaH
+1. Люди застраховали свой зад от какого-то определённого класса ошибок в каких-то определённых случаях (по крайней мере, они так считают), и носятся с этим, как будто это решит все проблемы разработки ПО. Это не говоря уж о том, что everything comes for a price (причем даже не только и не столько в виде какого-то рантайм оверхеда, сколько в необходимости изобретать какие-то обходные пути там, где ранее все "просто работало" — с умеренным приложением головы, разумеется).
PsyHaSTe
Programming Defeatism: No technique will remove all bugs, so let's go with what worked in the 70s.
KanuTaH
Nope, я скорее про "закон дырявых абстракций" и "бесплатного сыра не бывает" :) Если бы "наворачиванием абстракции на абстракцию" можно было решать любые проблемы — ядра ОС и прошивки для железа уже писали бы на яве с шарпом. Там такое любят :)
PsyHaSTe
платность тут состоит в том, чтобы уметь этими инструментами пользоваться. Но как по мне, выучить единожды инструмент чтобы применять его N раз всегда имеет смысл. Программирование в этом и заключается, к слову. Но люди хотят автоматизировать все, кроме собственного быта. Некоторые.
Андроид на яве и написан. Singularity — на шарпах. Что до винды и линухов, тут то что называется "исторически сложилось". Нет никаких причин почему именно си, просто так вышло. Потому что популярно было в 70е. в нулевых популярной была жаба, андроид написали на ней. Сейчас раст достаточно популярен, фукси (новая ос от гугла вместо андроида) емнип на нем пишется.
Так что прогресс идет.
KanuTaH
Ядро Android написано на C/C++, никакой явой там и не пахнет. Ява там только как рантайм для приложений (и то не для всех — Android NDK никто не отменял).
PsyHaSTe
Я не считал точно, но жава-строк в андроиде явно больше, чем код ядра. Вся std библиотека и все остальное — это джава.
KanuTaH
Да, основной рантайм для пользовательских приложений там — это Java-классы (но не только, есть ещё и NDK). Но не ядро.
PsyHaSTe
Ну то есть "пишите код без багов". Так не бывает.
Повышение квалификации заключается в том, чтобы уметь работать с более серьезными абстракциями, а не помнить про каждую переменную в программе, какие могут быть NULL а какие нет.
Напомню, что человек не может держать в памяти больше 7 объектов одновременно, и это не зависит от квалификации.
Ну и отлично. Что расстраиваться-то?
Labunsky
Ну понятное дело, но и смена языка тоже не спасет)
Про помнить каждую переменную и количество объектов не понял, опять же, в чем именно си хуже любого другого языка. К слову, в нем нет NULL'ов, зато есть самые обычные нули
Как чего, падению квалификации. Софт-то кому-то писать надо, нам же его и использовать, если доживем
PsyHaSTe
Вполне. От некоторого класса проблем. Чем серьезнее язык, тем больший этот класс.
Ну вот я не могу без подсказки от системы типов что это
Option<T>
помнить, что тут нулл выскочить может.Ну а это типичное "раньше было лучше".
KanuTaH
Ну, смотря в чем «лучше». Типичный Java/C# (а тем более JS) разработчик сейчас, как правило, не имеет понятия ни о том, как работать с памятью, ни о приемах оптимизации кода в плане правильного использования кешей, ни о том, как внутри себя устроены какие-нибудь мутексы, и к чему приводит их использование в плане производительности. Да что там говорить, он даже не особо интересуется, к чему «внутри» приводят его попытки конкатенации строк «в лоб», через оператор "+". Не царское то дело. Как только нужно будет написать что-то действительно оптимальное, такой разработчик тут же сдуется, упрется в порог инструментария. Он просто не будет знать, что можно как-то по-другому. С другой стороны, человек, имеющий опыт относительно низкоуровневого программирования, как правило, все же задается вопросом «а что там под капотом», поэтому он даже на всех этих «абстракциях» пишет лучше, чем граждане, пишущие исключительно на «удобных» языках, а главное — он всегда имеет выбор.
P.S. Вот выше johnfound написал «все выше пишут как будто производительность все еще удваивается каждые 18 месяцев», его сначала даже заминусовали, я помню, а я вот сразу понял, о чем он. У меня те же ощущения.
PsyHaSTe
Да-да, а типичный C++ разработчик не знает о поколениях ГЦ, как работает хотсвап джиттер и прочее. Что из этого следует?
Да, только потом оказывается, что они в курсе, как это работает, и конкатенация через плюс оказывается быстрее, чем попытки плюсовиков ускоирть жс через стрингбилдеры какие-нибудь. Уже проверяли тут же, на хабре.
Советую не тешить в себе ложный элитизм.
KanuTaH
Почему же? Если он начал писать на managed-языках, он узнает. Может быть, даже напишет свой. У него даже вполне может быть для этого необходимый background.
Не в курсе про жс, но в Java компилятор таки пытается заменять такие «лобовые» конкатенации на работу через StringBuffer:
docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.18.1
Но он может и не справиться с такой оптимизацией в один прекрасный момент. А гражданин, который «в курсе как это работает, и конкатенация через плюс быстрее» будет чесать репу — как же так, раньше же быстро работало, а тут вдруг тормоза не пойми откуда. Всегда работало, а тут вдруг перестало.
:) Я учту :)
PsyHaSTe
Ну вот если у жсера начнутся проблемы с памятью, он точно так же узнает про её устройство и сможет оптимизировать.
Такова жизнь манагед-разработчиков, что кроме процессора у него еще есть ВМ, и он должен знать поведение джита и рантайма в таких-то условиях. Тоже некий уровень сложности, который нужно учитывать.
Правда, очень рад. Нечасто такое слышу.
KanuTaH
На самом деле у меня лично просто есть забавная история как раз про случай, когда оптимизатор JIT'а с этим не справился. Меня просто попросили переписать некий кусок на плюсах, потому что «плюсы же быстрее». Переделав в этом куске конкатенации в цикле в цикле в цикле на StringBuilder (там не требовалась синхронизация), я ускорил кусок в разы for no charge, и продолжил лентяйничать дальше. Это я не с потолка взял пример, это моя личная боль :)))
PsyHaSTe
Да я понимаю, в шарпах та же проблема. Но жс как раз на этот случай имеет эвристику (точнее v8). Проверяли на разных версиях, результат стабильный. за жабу говорить не буду, скорее всего там такого нет.
Labunsky
На самом деле, раньше сборку мусора писали как раз для C/C++
Labunsky
Это защита из серии мягких углов. Да, маленького ребенка нельзя одного оставлять в помещении, нужны и заграждения, и надзор, и разъяснения, что в рот брать надо, а что нет. Но чем он становится старше, тем больше свободы мы ему даем: сначала доверем ему ПВА для апликации на уроке труда, позже паяльник, а потом и вовсе сварку. Потому что с опытом тот начинает понимать, что и как ему делать, используя полученные знания с большей эффективностью. Даже если неаккуратное использование и опасно для здоровья
Поэтому я не против разработки строгих и сколь угодно беопасных языков, сам могу на них писать даже. Но не нужно предлагать заменить опасную сварку по железу на безопасный пва по дереву. Да, иногда результат будет даже лучше. Но для остальных все еще имеет смысл одолжить аппарат и маску у соседа
PsyHaSTe
Только лучше эту опасную сварку применять точечно, огораживая ~unsafe~ знаком ОСТОРОЖНО: СВАРКА.
И если что-то пошло не так, сразу понятно, куда глядеть.
anatolymik
Ежели серьезно, на мой взгляд, дело в человеке, а не в инструменте. Правда это другая крайность. Безусловно удобные и эффективные инструменты должны быть.
Labunsky
Это и моя же позиция)
Вот только почему нынешние неудобные? То есть, тот же раст на самом деле имеет кучу интересных фич, но зачем-то позиционируется многими как замена си со смущающей меня аргументацией. Так тяжело существовать параллельно, что ли?)
anatolymik
Безусловно да. Ибо человек, который знает только один язык, ограничен в восприятии контекста решаемых задач. А значит все должно быть как у него :) «Когда в руках только молоток, все начинает казаться гвоздем».
Я не могу сказать что они так уж в основе не удобны. У каждого из, есть как плюсы так и минусы. Поэтому я за совмещение подходов, а не за то чтобы подвести все под одну черту. В любой подобласти нашей сферы, есть своя специфика. Ну и это безусловно подводит нас к тому, что и инструменты будут разными и с разными возможностями. Мы ведь не запускаем самолеты с ракетной площадки. Мы контекст задачи учитываем.
Так же и тут. Я и не против того чтобы все унифицировать. Но наша индустрия еще не выработала всего нужного. Есть legacy, есть лишнее, а что-то отсутствует. За много лет её существования поменялся ряд задач, которые мы решаем. Многие из них перестали вписываться в ту картину которая сложилась. Нужно переосмысление всего. И как следствие выработка новых подходов, механизмов и аппаратуры. А людей, которые решат данную задачу, просто нет. Потому что и спроса на них нет. А ведь это исследовательская работа, которая требует очень длительного вовлечения по времени. Ситуация осложнена тем, что корпорации деньги зарабатывают. И развитие как таковое отсутствует. Рынок насытился, и все думают о том чтобы прибыль осталась на том же уровне.
Я в прошлом, стремился к тому же самому. Все упростить. В результате пока решал эту задачу, разобрался много в чем. И надобность унифицировать отпала. Нет ничего сложного чтобы совмещать подходы. Сложно придумать это совмещение. А стремление было вызвано тем, что когда я что-то новое узнавал, мне казалось что я теперь все знаю и хотел всем жизнь облегчить. А по факту испортил самому себе. Время только потерял. Но не все так уж и печально. Лучшее что я вынес из этой практики, так это то, что такая унификации сейчас, ведет к переусложнению, избыточности и излишней нагрузки на вычислительные системы.
Поэтому, люди которые однозначно стремятся все унифицировать, мне видятся либо не опытными специалистами, либо специалистами которые не дают никакой оценке проделанной работе, либо они просто пластинка. На работе таких много, постоянно с ними борешься. В результате, придут, своими решениями все сделают хуже. После чего они получают пинка под зад, а после идут в другое место портить там. А далее, начальство на их место садит таких же, если не хуже. Ну, зато не скучно. Не работать же :) Категорично вроде, но не лишено смысла. Сам таким был :)
PsyHaSTe
Неудобство понятие относительное. Например, ассемблер неудобнее Си, а си неудобнее раста. Через 20 лет будет язык удобнее их всех. И еще через 20. Развитие в том и заключается, что палки-копалки и камни превращаются в экскаваторы и отбойные молотки. Заметьте, мы не заставляем людей научиться выкапывать по 20 тонн земли в час, мы меняем инструменты. Даже если взять лучших копателей за всю историю и заставить учить людей как это делается вы не сможете достичь результатов техники. Потому что люди это люди. Они ошибаются, они часто теряют внимание, да и в целом рассеяные. Ожидать от них полной самоотдачи и внимательности 24/7 немного наивно. Лучше дать инструмент, который скажет "чел, ты переменную используешь, я такой не вижу. Может ты ошибся"? или "А тут у тебя ошибка может возникнуть, а ты никак не обрабатываешЬ", или "Вот ты версию библиотеки обновил, а вместо
Т
у тебя тутOption<T>
начал приходить, обработай, дорогой".Labunsky
А в чем измеряем? Явно не количеству слов и символов, необходимых для реализации одних и тех же действий — курс формальных языков создатели последнего не сильно любили
Этот инструмент зовется "анализатор". Статический подвид входит в практически любой современный компилятор, иногда даже отдельным модулем. Благодаря этому, последним можно выставить обработку предупреждений анализатора как ошибок компиляции, чтобы "почти как в расте". Все уже придумано за нас)
Так не все делают по простой причине — часто нет времени вылизывать все дочиста, если код может работать и так. Хотя сейчас становится проще и редакторы учатся проводить анализ в процессе написания кода, чтобы можно было чинить по факту
Но на самом деле, 2/3 примеров не пройдут даже лексический анализ
PsyHaSTe
На первый вопрос проще всего взять уже известное мерило
Насчет второго раст это и есть плюсы с прикрученным анализатором, в котором язык чуть-чуть подправили чтобы анализатор был точнее. Если посмотреть раст образца 2008 года, то это что-то среднее между плюсами и сегодняшним растом. Причем с тех пор по сути поменялся только синтаксис на более мл-подобный, но судить язык по синтаксису это такое.
Ну вот я считаю, что в программе не должно быть CVE с памятью вообще. Даже если код "ну типа работает". Это не те проблемы, на которые можно забить в приложении, если только это не прототип.
Labunsky
Мы этим уже занимаемся. Наши физические компьютеры — ее модели, мы просто используем синтаксическую прослойку, которую разворачивают компиляторы, интерпретаторы и виртуальные машины
Эти знаки точно так же ставятся в любом другом языке. Всегда заранее известно, какие операции могут привести к какому результату, ЯП полностью детерменирован
На два стула сесть не выйдет. Если писать полностью без unsafe, то можно легко натолкнуться на повышенный расход памяти (эти умные указатели любят позависать). Глобально надо смотреть в сторону сборщиков мусора, позволяющих совмещать подходы. И тех же самых, что и для C/C++, динамических анализаторов типа valgrind
mayorovp
Со сборщиками мусора та же фигня: да, простой оторваный цикл они соберут. А вот как бы удаленный объект, забывший отписаться от событий — уже нет...
Labunsky
Главный плюс сборщиков мусора в языках с контролируемой памятью в том, что им можно явно дать комманду освобождения. Тогда они сами будут лишь утечки собирать, не сильно влияя на корректно работающий код
Ryppka
Свободу сборщикам мусора!)
Если честно, не совсем понял, что имеется в виду: при каких-то настройках gc собирает не только освободившуюся память или дурно влияет на корректно работающий код?
Labunsky
Имел ввиду, что gc может ждать, пока память станет свободной по его мнению, а может получить явный вызов по освобождению объекта "здесь и сейчас"
Дурно он влияет на производительность: большое число объектов отслеживать и обрабатывать сложно. Поэтому программист может ему помогать, делая такие вызовы на части объектов заранее
mayorovp
"На часть объектов" программист не может сделать вызов GC по определению мусора: если у программиста есть способ указать на объект, то он точно мусором не является.
Labunsky
Почему нет?
mayorovp
Как это работает? И что будет, если я сделаю вот так?
А если без вызова gc_free?
Labunsky
Зависит от реализации, конечно, но обычно: в глобальной переменной будет храниться адрес на освобожденный участок в памяти, а обращение к ней — UB
Если без вызова — то будет висеть, так как завязан на глобальную переменную, куда ему деться
mayorovp
Ну и какие тогда преимущества у подобного сборщика мусора перед нормальными умными указателями?
А как он поймет, что есть такая переменная и там находится именно указатель?
Labunsky
Если мы где-то забудем освободить память, но и в глобальную переменную не запихнем, он ее отследит и освободит без волнений. Помимо прочего, обычно они защищают нас от double free, проверяя, есть ли освобождаемый объект в использовании. Нужно брать лучшее от обоих миров)
Ну как сборщик мусора ищет сами указатели и их обрабатывает — это можно очень долго и много писать)
В общем случае, сканируются регистры, стэк и статичные регионы типа data (как раз случай глобальной переменной). Для каждого найденного указателя f просто проверяется, есть ли в базе объектов (обычно это простая таблица) такая пара (p, size), что p <= f < p + size. Если есть — объект, описываемый парой, в использовании, то есть не мусор
vvmtutby
mayorovp
Прав конечно же. Но утечка ресурсов от этого не исчезает.
TargetSan
Увы, нет. И С/С++ с их просто огромным количеством UB/ID тому вполне себе подтверждение. Вы не можете в С сказать "нулевые указатели у меня будут только здесь, в других местах их не пропускать". Так что программа на С/С++ будет представлять из себя здание с огромным ОСТОРОЖНО СВАРКА во весь фасад.
И да, я хочу чтобы компилятор бил меня по рукам за использование инвалидированных итераторов. Потому что я человек и периодически делаю глупые ошибки.
Labunsky
Появление UB — это детерменированное поведение. Мы всегда знаем, где он есть, а где его нет, это четко прописано в спецификации. Просто не знаем заранее, какой из возможных результатов скомпилируется. Недетерменированные автоматы же на x86 никак не загнать
Halt
В таком случае UB sanitizer был бы тривиальным. Проблема в том, что определены только условия наступления UB, но не то, есть ли он в данном конкретном примере кода или нет. В общем же случае, сюда еще набрасывает проблема останова.
Поэтому единственно достоверный сопособ исключить UB — предотвратить его статически, на уровне системы типов.
Labunsky
Большое его подмножество и. Сложно найти неинициализированную переменную? Да ну нет. Знаковое переполнение? Да тоже просто. Нал поинтер? Куда проще
В общем случае найти их все вроде как нельзя, да, но тут никакой язык не спасет
Пока не вышло
PsyHaSTe
Уб специально завозят для того, чтобы не писать анализатор, которые его ловит, потому что это сложно. Каким образом кто-то другой напишет анализатор, если разрабы языка сдались в этом вопросе?
0xd34df00d
Особенно после того, как код был скомпилирован с оптимизациями, полагающимися на то, что UB в коде не бывает.
Labunsky
Такой поиск проводится до стадии оптимизаций
0xd34df00d
UB может возникнуть после инлайнинга, например.
Да и вообще,
В каком месте вы тут «очень просто» (то есть, как минимум, без cross-TU analysis) мы что-то про null скажем?
Labunsky
Нигде, потому что он явно передается программистом, исполнение и последующее падение будет полностью корректным запланированным поведением. Вот если он случайно появляется из вызова или операций...
0xd34df00d
Я надеялся, что пример будет очевидным, так как это пример и призван быть немногословным.
Будет вам легче, если я вместо
nullptr
там подставлю вызов функции, которая потенциально может вернутьnullptr
?Labunsky
Ну да, потому что тогда мне моя иде нарисует предупреждение о проверке на NULL. Такие ошибки легко ловятся простым фильтром: необходима проверка либо до доступа, либо после изменения. И кто мы-то, я один тут)
PsyHaSTe
Нет, вы этим не занимаетесь. Вы пишете на своих удобных ЯП а во что оно трансформиуется уже вопрос десятый. От того что хачкель компилируется в х86 ассемблер вы не теряете его мощи, гарантий и ленивости.
Скажите, если у меня есть сегфолт в программе на Си, каким грепом мне найти все конкретные места, где теоретически он мог возникнуть?
С чего это? Ансейф не имеет отношения к повышенному расходу памяти.
Все считается в компайл тайм, какие зависания?
Labunsky
Только если для страуса в песочнице. Надо понимать, какой код переходит в какую последовательность инструкций, для этого даже есть удобное по. В идеале, надо уметь и на машину поста/тьюринга писать программы: необходимость писать даже регистры и операции над ними с нуля дает отличное понимание компьютерной архитектуры
Ансейф — нет, а умные указатели и система владения — имеют. Компилятор не программист, он не обладает способностью к аналитическому мышлению
Зависания как у не самой умной молодежи: соберутся в кучку с пивом, включают блютуз-колонку шумят, занимают место, отказываются уходить
PsyHaSTe
Для большинства софта. Потому что это называется абстракция.
Занимался этим на курсе матолгике в универе, давно. Смысла в практическом программировании у такого ноль ровно. Даже знания кэш локалити полезнее.
Я написал бота для телеграма который анализирует семантически картинки и определяет похожие без единого умного указателя. Так что они нужны в исключительных случаях.
Labunsky
Неужели вас заставляли курсе на втором выделять на ленте регистры и память, писать операции над ними, а потом применять их ко входных данным на ленте? Думаю, нет. В основном потому, что:
Без "такого" не будет практического программирования, потому что нечем будет компилировать, не на чем исполнять)
PsyHaSTe
В машине тьюринга нет никаких регитсров, там есть только бесконечная лента и алфавит. И да, мы этим занимались.
Ох уж это гадание по интернету.
Знаю людей, которые никогда такого не делали, но им есть на чем компилировать. Как так?
Labunsky
Регистры на ленте машины тьюринга/поста нужны для ограничения областей на ленте под операции, изначально их нет, они не обязательно нужны, но очень помогают не сойти с ума. А еще с их помощью можно написать компилятор, а не руками команды набирать)
Да, можно писать на джаве под спринг, собирать все градлом, под капот ни одной абстракции не залезать. И быть легко заменимым
0xd34df00d
С учётом ?Ops хоть?
А программы в исчислении SKI уметь писать надо?
Ну, мне просто интересно, где ваше «надо» заканчивается.
А знание того, что такое исчисление SKI и какие у него свойства, мне было нужно не далее как две недели назад, тогда как написание под машину Тьюринга мне нужно было примерно никогда, кстати, но то такое.
Labunsky
Нигде, процесс учебы не является чем-то конечным
И можно было одним постом написать все, а то я аж испугался количеству входящих на почте
0xd34df00d
Только некоторые языки, увы, не требуют этого ставить.
0xd34df00d
Только когда язык изначально спроектирован с использованием анализатора (который в таком случае называется системой типов), оказывается, что анализировать можно точнее и с большим количеством отлавливаемых проблем.
Labunsky
На практике это пока никем не продемонстрировано. Синтаксис нас ограничивает уже сейчас, заявления есть, а супер-надежного ПО — нет, как и массовой миграции
0xd34df00d
То есть, все те люди, которые пишут на всяких Coq и Agda формально верифцицрованные вещи, ничего вам не демонстрируют?
Ну ок.
Labunsky
Пишут много кто и много на чем. Это не значит, что ошибок меньше, а если меньше, то из-за языка
Но я рад, что вы тут все сбондились, мне за пару комментариев минусов уже прелетело больше, чем за последние 4 поста пришло. Комьюнити выходит дружное, но не мотивирующее
0xd34df00d
Что-то мне подсказывает, что про всякие там коки, и как и что на них пишется, вы не особо слышали.
Labunsky
Так точно, коки принимаю только в форме листьев по праздникам, как и любой другой не очень умный человек
Ryppka
Для многих низкоуровневых задач C удобнее Rust'а. Такие задачи обычно невелики, а синтаксического шума в C меньше, так что меньше и возможность описаться или еще как ошибиться. C создан для таких задач, а Rust делает их решение возможным.
Преимущества у Rust'а появляются при масштабировании задачи.
PsyHaSTe
Ну так если посмотреть на правила приемки самолетов, то там не си используется, а его подмножество удивительно похожее на какой-нибудь раст опять же. Только вместо системы типов и компилятора там ручная проверка и, возможно, тесты.
Человека нельзя кардинально поменять. Нельзя сказать "с завтрашенго дня пиши без багов". Человеку можно дать более удобный инструмент, но и все.
anatolymik
Речь по-моему не о багах. Кардинально можно уволить. А в утверждения типа «пишет плохо но круто идеи выдает» я давно не верю. Т.к. многократно видел что это не так. И т.к. если человек плохо разбирается в деталях, то и в глобальным смысле он видит еще меньше. Если человек не может кардинально меняться, ему надо менять профессию. Например на стройку пойти работать. Если конечно у него задача найти свою нишу. А если в целом, я не пойму откуда такая любовь к таким людям. Я с такими даже говорить не стану(в профессиональном смысле, профессионализм на человеческие качества никак не влияет). Что уже говорить о том, чтобы считаться с ними. Интересно выходит, делают хуже, а требуют к себе равного отношения. «Защита прав слабоумных».
Можно, и инструмент нужно улучшать. Но сути само по себе оно не меняет. Если человек на менее удобном инструменте не мог выполнять работу нормально, то он и на более удобном не сильно то себя проявит. Потому что основ не понимает. А бывает еще когда дурака грамота только портит. Скажем так, с удобством инструмента, должны расти и требования к задачам. А если так, то планка по задачам снижаться не будет, с чего бы ради он будет делать нормально, когда в голове больше двух переменных удержать не может? Но если планка не повышается, а инструмент удобнее и проще, и как следствие он ту или иную задачу уже может выполнить, то он, выходит обезьяна. Т.к. по сути по методичке уже делает, не понимая основ. И в том и в другом случае, мне видится, дело в человеке.
PsyHaSTe
Просто если есть бесплатные бенифиты, то почему бы ими не воспользоваться?
Нет, речь как раз о баге. Типичный пример, когда забыли проверить на нулл и разыменовали нулевой указатель. Или у вас такого не бывает?
Если человек не знает физику, то микробиологом ему не быть, потому что он основы не понимает.
Простите, но нет. Есть известный закон дырявых абстракций, который явно говорит, что достаточно знать +-1 уровень от своей текущей чтобы полноценно выполнять свою работу. Кругозор — это полезно, никто не спорит.
Но как уже сказано, знание "С++" никак не делает челвоека более хорошим разработчиком, чем знание C#.
anatolymik
В C# тоже бенефиты, например память освобождать не надо. А как следствие сбурщик мусора требует процессорное время. И память освобождается дольше. И если тоже самое делать на С++, то результат себя лучше покажет, когда речь о высокой нагрузке. Вы не будете с этим спорить?
Бывает. Когда я драйвер пишу, у меня DriverVerfier включен постоянно. Когда приложение, то memoryleakdetector прикомпоновываю. Все возможные инструменты проверки у меня работают постоянно. И я отлаживаю то что пишу, даже если в функции две строчки. И прорабатываю под отладчиком все возможные пути работы той или иной функции. А потом в комплексе все смотрю. Это не сложно. Обычная проверка того, что делаешь. Но, те о ком вы говорите, так не заморачиваются. Потому как им просто лень. Возникает вопрос, а зачем такой пассажир нужен? Как вы ранее упомянули, людей не поменяешь. Я, понимая это, по возможности буду избегать с такими встречи. И не буду входить в положение их тонкой и ленивой натуры.
А смена языка равна смене профессии? Языки высокого уровня, по сути ускорили разработку. Языки с «бенефитами» не только ускорили, но и ограничили. Поэтому и область применения у них разная.
Я переформулирую свой тезис. Раз речь о багах, и тем более если речь о багах, сути оно, тем более не меняет. При разработке чего-либо(т.е. при решении той или иной задачи, я это так называю), вы вырабатываете решение, концептуальное. У одной и той же задачи решений может быть несколько, со своими как плюсами так и минусами. И нередко приходится совмещать разные решения в одно. Чтобы качества добиться. Так вот если человек в принципе концептуально не умеет решать задачи, язык ему не поможет. Ибо в логике решения задач у него проблемы. А null dereference и иже с ними здесь всего лишь детали. А человек который умеет решать задачи, управиться с такими проблемами.
Скажите, а ассенизатор хорошо выполняет свою работу?
Я говорил не о кругозоре, я говорил о профессионализме. Если вы умеете только что-то одно, вы не сможете решать более сложные задачи. Потому что не знаете ничего в смежных областях. А если и знаете то не факт что понимаете до конца, т.е. это уже опыт. А чтобы создать что-то реально новое, нужно знать очень много. Т.к. хорошие решения на самом деле, решаются не на одном уровне.
Никак, согласен. Только, знание только С# тем более.
PsyHaSTe
Окей, давайте не будем.
Вполне вероятен сценарий, где C# будет лучше за счет той же компактификации кучи, откуда кэш локалити и вот это все. Смотреть надо по ситуации.
Они работают на эвристиках, и проверяют реальное изменение. Вы ведь понимаете, чем компиляция лучше дебага или даже тестов? Тем, что проверяются все возможные пути, а не только те, по которым программа до этого ходила.
Мое мнение такое, что если что-то можно автоматизировать, то это надо автоматизировать. Например, нахождение нуллов. Или рейс кондишны. Или еще что. Лучше иметь компилятор, который отследит все случае, чем сидеть каждый раз руками с валгриндом и сравнивать. Не говоря про то, что правильно работать с таким инструментом сложнее, чем с комилятором, который может чуть ли не код фикса написать самостоятельно, который надо только скопипастить чтобы все заработало.
Наверное
В штатах есть такое понятие, как overqualified. Не встречали?
Все равны
Но некоторые равнее :)
anatolymik
Не даст он никаких преимуществ. Пара тройка максимум. Из всего спектра проблем. А компактификация и кэш локалити появились только потому что он на этапе своего рождения породил проблемы, которые необходимо было устранить. Иначе он бы не родился.
Плохо работают? 99,9% ловят, еще на этапе разработки.
Проверки времени компиляции, не хуже и не лучше. Они просто есть. И их наличие упрощает разработку. Панацея?
Хоть один компилятор покажите, которые не даст вам ошибиться. А то на расте у вас проблем нет. Все идеально.
Придерживаюсь такого же подхода. Вот только что-то одно не панацея.
Рейс вам не один компилятор не покажет. Для этого ему уже надо понимать что вы пишите, а он не понимает. Когда начнет понимать, вы пойдете таксистом работать.
Я вот не пойму что все носятся с этими нулами? Я допускаю эти ошибки. Но редко. В алгоритмах и подходах я ошибаюсь постоянно. Что компилятор уже не ловит. Складывается ситуация, что есть машина, а вожу плохо. Вывод — плохая машина. Интересные вы люди.
Лучше, только никто еще этого не сделал. Для этого ему надо делать анализ кода, пока что и это плохо получается. И по факту, работать надо с тем что есть, а не мечтать о том, как было бы правильно. «Хочу чтобы было хорошо». Да я тоже хочу, дальше то что?
А штаты эталон чего-то? И упомянутый термин тут к чему упомянут? Какое отношение он имеет к компиляции и удобству языков? Сказать нечего, но сказать надо. Я правильно понимаю?
И что до термина, придумали его эффективные менеджеры. Потому что им сиюминутно нужны бабки и чтобы поток их был стабильным. Не понятно как это происходит?
Особенно они не любят, когда с ними спорят. Например, когда вы настаиваете на том, чтобы сделать хорошо. А не дрянь. Вы тут же получите ярлык что вы конфликтный. Это их мнение вы призываете меня слушать? Я таких даже людьми не считаю.
Про штаты вы мне можете не рассказывать, ровно как и про наше. Я про ИТ сферу. И по факту, эти менеджеры засерают мозги молодым специалистам, из-за чего они не вырастают. И в результате, вся сфера сейчас переживает падение качества. Причем стремительное. Старцы на пенсии, а молодые новаторы(я их так называю) ничего высрать не могут. Т.к. вечно недовольны инструментарием и мечтаю о лучшем загробном мире.
Термин появился только потому что в нашей сфере назрел кризис, и специалисты просто не востребованы. А менеджеры хотят погоны. Ну? Это ихние термины я должен слушать? Они могут себе их задницу засунуть. Ровно как и те кто их повторяют. Отношение к последним у меня примерно такое же, как и к авторам подобных высеров.
Я равнее, да.
Ryppka
Никогда не понимал тех, кому для признания в любви к языку А нужно ругать язык Б. Я люблю и C и Rust, но последний люблю за его возможности, а не за то, что в нем нельзя сделать трудно уловимые в C ошибки. Для меня это просто приятный бонус, за который приходится расплачиваться.
ncr
иллюзию полного и явного контроля.
abondarev Автор
Я думаю имеется в виду, что контроль гораздо более полный и явный чем в управляемых языках
Parondzhanov
abondarev писал:
Вы правы. Продуманные ограничения уменьшают риск написания небезопасного ПО.
Вспомним. Эдсгер Дейкстра ввел ограничение, указав на опасность goto.
Затем Бертран Мейер ввел ограничение, указав на опасность break и continue.
Развивая линию Дейкстры-Мейера, можно ввести дополнительные ограничения, указав на небезопасность служебных слов, организующих поток управления: goto, break, continue, if, then, else, case, of, switch, while, do, repeat, until, for, foreach, loop, exit, when, last и их аналогов.
Исходя из этих соображений, в визуальном языке ДРАКОН (во имя безопасности потока управления) исключены опасные служебные слова, организующие поток управления: goto, break, continue, if, then, else, case, of, switch, while, do, repeat, until, for, foreach, loop, exit, when, last и т.д. Вместо них используется математически строгая графика управления, которая реализует ту же самую функцию, что и перечисленные служебные слова.
В чем идея? Наибольшую вероятность появления ошибок создают разветвления и циклы. То есть конструкции, описываемые указанными служебными словами.
При использовании языка ДРАКОН функции, реализуемые указанными служебными словами, не записываются вручную, а формируются автоматически. Поэтому вероятность ошибок, вызванных разветвлениями и циклами, уменьшается или сводится к нулю.
Таким образом, при использовании ДРАКОНа (при описании потока управления) остаются лишь опечатки и ошибки, появляющиеся на ЛИНЕЙНЫХ участках программ. Однако такие ошибки можно сравнительно легко выявить и устранить.
bit.ly/2Mlg4Ou
bit.ly/1UQ4zuU
habr.com/ru/post/345320
drakonhub.com/files/pe_drakon_automata_mitkin_2019.pdf
С уважением,
Владимир Данилович Паронджанов
Mobile: +7-916-111-91-57
Viber: +7-916-111-91-57
E-mail: vdp2007@bk.ru
Skype: vdp2007@bk.ru
Website: drakon.su
Webforum: forum.drakon.su
abondarev Автор
Да, про Дейкстру и Мейера тоже было в контексте Оберона. А в кулуарах даже рассуждали об использовании графических языков в АСУ для АЭС. Но лично мое мнение, что графические языки имеют достаточно узкую сферу применения. Для определенных задач они действительно хороши, но например для написания ядра ОС, точно не подходят.
staticmain
>А в кулуарах даже рассуждали об использовании графических языков в АСУ для АЭС
Недавно на хабре пролетало, что там графический язык программирования, который транслируется… в С.
abondarev Автор
SCADA обычно состоит из минимум двух частей, РМО (рабочее место оператора) там используются мнемограммы, и рантайм управления. Вот рантайм может быть как на графических языках (Стандарт МЭК 61131-3 ), так и не на графических например на Обероне. Об этом можно например на хабре посмотреть тут
mayorovp
Предлагаю исключить любое написание программ вообще, и закрыть на этом эпоху информационных технологий. Во имя безопасности человечество, конечно же.
Дракон — это пример того, как не должен выглядеть визуальный язык программирования. Он неудобен, даже антиудобен. Программы на Драконе хороши тем, что их можно вставить в
рамочку и повесить на стенукнигу или презентацию в качестве иллюстрации. Но их очень сложно редактировать (когда я смотрел Дракон последний раз — там нельзя было перетащить блок в другое место, только удалить и создать заново), а ведь написание программы — это последовательность редактирований...Пример удобного визуального языка программирования — Scratch. Он точно так же, как и рекламируемый тут Дракон, формирует все управляющие конструкции целыми кусками — но при этом очень прост в редактировании.
Проблема подобный рассуждений — в том, что в них неявно предполагается, что синтаксические ошибки опаснее алгоритмических. А это не так. Синтаксическую ошибку, как правило, довольно просто заметить и исправить — а кривой алгоритм будет глючить долго.
PS нет смысла писать контактные данные под каждым комментарием — для них существует профиль пользователя
anatolymik
Не поленился и ознакомился по диагонали с драконом. Изучить надо не мало. Чтобы этим пользоваться. Вот и вопрос, чем проще то? Можно подумать блок-схемы читать удобнее. Дело привычки конечно. Но по-моему последовательно написанный текст будет информативнее. Да и транслятор этого не будет оптимальным.
Ну не записали вы их вручную. Ну автоматически будет сгенерировано. Сгенерировано будет все равно исходя из того что вы задали на входе. А если вы на входе зададите неправильно, что ветвления правильными вдруг станут?Вообще странное утверждение. Из которого следует чем сложнее алгоритм тем легче в нем ошибиться, потому что текста много. Можно подумать на драконе ничего для описания этого же алгоритма делать не надо будет. Ну будут у вас не такие ошибки как на классических языках. Будут другие. Разница то в чем?
Siemargl
Справедливости ради, графические языки (безотносительно дракона) гораздо удобнее в отладке, особенно когда не имеешь права поставить точку останова (любое работающее оборудование).
Ryppka
А еще они удобны при использовании систем контроля версий…
mayorovp
Надеюсь, это был сарказм.
Ryppka
Поверили?! )))
Siemargl
Это решаемая задача. И да, очень нужная — которую надо закладывать в инструментарий при его проектировании.
Ryppka
Пример решения?
Siemargl
Сейчас проекты экспортируются в текстовый/Иксмл формат и могут сравниваться.
В принципе, я читаю например Роквелловские или Сименса текстовые диффы для релейки.
Но в целом потому говорю, что нужно закладывать при проектировании — визуальному языку нужен и визуальный дифф.
Ryppka
Ох-ох, личный опыт с парой визуальных инструментов с xml-бэкендом и парой основанных на xml «языках» программирования терзает мою душу смутными сомнениями…
mayorovp
XML — это не столько решение, сколько костыль. Да, так делать можно — но в итоге разработчику нужно будет знать уже два языка (визуальный и его XML-представление). То есть визуальный язык перестает быть чем-то самостоятельным.
Визуальный дифф звучит куда лучше, вот только я не слышал ни об одном таком проекте.
Parondzhanov
.
anatolymik
Вы знаете, я много лет пишу и сложные функции в том числе, и из вами здесь приведенного не вижу ничего чтобы усомниться в том что классический подход менее эффективен.
А может, прошло время, и у человека в голове к моменту переноса все уложилось по полкам? А язык оказался не причем? Т.е. это было совпадение. Один случай на мой взгляд ничего не доказывает. Нужно вести статистику и из неё вычислять среднее значение.Относительно комментариев вроде:
Чтобы разговор был предметным, хотелось бы увидеть реализацию на Си и на драконе. После можно уже что-то пытаться обсуждать.
А пока что, на мой взгляд, это личное предпочтение и убеждение разработчиков графического языка. И в этом ничего плохого. Просто мне так видится ситуация.
mayorovp
Рад за Сергея, но все ещё не понимаю пользу Дракона для нормальных программистов.
Пустой набор слов, которые вместе ничего не обозначают.
Не слышал о таком.
anatolymik
Когда говорят о безопасности, надо понимать контекст. А конкретный пример чего-либо, сам по себе может еще ничего не доказывать.
Си безусловно устарел. Но, на мой взгляд, попытки сделать достойную, учитывающую все тонкости альтернативу, пока тщетны.
abondarev Автор
Ну это Вы загнули конечно. А где же тогда выделяются локальные переменные (память под них)? Или как по вашему происходит вызов функции, в смысле передача параметров?
anatolymik
Я другой пример приведу, в процессорах Itanium стек данных и стек вызова развязан. А в будущем поколении процессоров Intel будет shadow stack. Что автоматически защищает от buffer overrun. Имеет ли язык Си к этому отношение? Что будет со стороны ОС сделано чтобы оно заработало? Надо ли будет дорабатывать компиляторы? По всем вопросам однозначно нет. А если так, возникает вопрос, как это получается, что появление аппаратного механизма делает абстрактный язык Си — безопаснее?
Наверное у нас изначально разница в терминах. А значит и говорить не о чем.
abondarev Автор
Ну зачем Вы пишите, если говорить не о чем?
По этим двум вопросам однозначно, да!
Вот мы тут портировали Embox под Эльбрус. Embox это ОС и там пришлось работу со стеком (при переключении контекстов) сильно замысловатым делать. Ну и конечно, как работать со стеком для конкретной архитектуры (и даже конкретного ABI) компилятор должен знать.
По поводу синтаксиса языка Си в привязке к стеку. Вообще то все языки программирования неявно имеют представление об управлении памяти, и базовыми являются всего три конктрукции: выделение памяти на стеке, выделение памяти в куче, и глобальные переменные. Часть языков, вообще запретили всякие глобальные переменные, и оставили только стек и кучу.
Но согласен, об организации данных в памяти прикладной программист зачастую не задумывается.
anatolymik
Со стороны ОС поддержать новый процессор. И делается это на языке Си который не знает ничего об этом. Компиляторы дорабатывать не надо. Ибо они не будут напрямую работать с shadow stack, учитывая его архитектуру.
Управляет памятью, менеджер памяти конкретной операционной системы. Память на стеке(в свою очередь выделенный операционной системой при аппаратной поддержке процессора), выделяет сама программа, сгенерированная компилятором для конкретной архитектуры.
А что вам мешало использовать встроенные средства языка Си для переключения контекста? Мы ведь уже выяснили что язык Си связан с термином стек.
Нонсенс. Как получается что на MSVC я под Linux бинари собираю?
Я нигде этого не утверждал, поэтому не понимаю в чем вы со мной согласны.
Вы лучше на этот вопрос ответьте. Как я уже сказал, по двум пунктам из трех — однозначно нет. Пояснения выше. Один пункт, это поддержка процессора. Но не языком и даже не его компилятором. Ваш опыт портирования ровным счетом ничего не доказывает.
zloe_morkoffko
anatolymik
Коллега, это была ирония. Мне казалось, что в моих утверждениях видно какого мнения я придерживаюсь.
abondarev Автор
Вот именно, Вам казалось!
anatolymik
Да? А может кое-кто просто печатного текста не понимает? И не может сопоставить что собеседник говорил до, и говорит сейчас?
Мне не кажется, я знаю что не должен быть. А раз вам кажется, расскажите что и как должно быть доработано. Конкретно на пальцах, а не на уровне идеи. Я же говорю что не надо. Учитывая как работает shadow stack. Один раз включаем его на процессоре и все. Грубо говоря. Механизм спроектирован обратно совместимо.
Я такое утверждал? Более того, в контексте утверждения, не понятно о чем оно вообще. Чуть ниже объясняю.
Встречное? почему на MSVC x86 компилируется и под ARM и под ARM64 и под x64?
Компилятор так спроектирован. MSVC например, на, как вы говорите, ABI не завязан. Максимум instrinsic функции, которые реализует программист. Но сделано это для интеграции с операционной системой. Таких моментов не много. Только я подчеркну. Это все расширения языка. Расширения делает разработчик компилятора. И к стандарту оно отношения не имеет. Было время когда и расширений не было. Сделали их для удобства разработки для конкретных архитектур. И оно снова не имеет отношения к стандарту. Если в gcc этого не заложили, и вы на этом основании делаете выводы, то извините, проблема ваша.
Тогда вопрос, как тут язык оказался причем? Явно вы этого не утверждали, и стали оспаривать другой момент. Но тем не менее. Вы цитируете высказывания других людей без понимая дела?
Еще раз, укажите место в стандарте Си, где явно упомянута сущность стека. И если упомянута, то в каком контексте. Расскажите про встроенные функции языка для работы со стеком. Расскажите про встроенные функции для управления памятью. Из стандарта только. На язык.
Как область видимости доказывает существование стека? По-моему так компилятор интерпретирует исходный код. И не более того. В какой машинный код он транслируется делает какую-то разницу?
Вопрос был риторическим. И наводящим. Но поняли вы неправильно.
Тебя прямым текстом послать? Или неявно? Хочешь мозгами померятся, пиши в личку. Посмотрим…
mayorovp
Нельзя ли почитать об этом подробнее?
anatolymik
Увы, нет. Дело было давно, лет 7 назад и делал я это самостоятельно. Что забавно, возникла такая потребность примерно в таком же контексте. Это был спор. Я потратил неделю и сгенерированный код cl.exe компилятором я заставил работать на Linux. Написал утилиту. Нужно было преобразовать PE в ELF. Ну и куча чего по мелочи. Делал на базе х86. Для х64 заморочек больше, например нужно согласовать модель вызова. Преобразовал все и заработало. Т.е. имеем сам факт, что код сгенерированный компилятором от студии, нормально работает и в Linux.
За выигранный спор, мне ничего не вернули. :) Объяснено это было тем что преобразование не считается. Все хотели из коробки. О чем я заранее предупредил, как я буду делать. И на момент посвящения в мои действия, у них не было никаких вопросов и возражений. Но когда появился результат…
А спор считаю выигранным потому, что противоположная сторона от меня ничего не потребовала, тем самым признавая меня победителем, но не желающая этого признавать.
Собственно примерно как сейчас, с другим собеседником.
abondarev Автор
Наверное Вы правы, не стоит отвечать на такое. Но попытаюсь еще раз объяснить свою позицию, надеясь на наличие мозгов у собеседника.
Вам не кажется, что компилятор (бэкенд) должен быть доработан. Поскольку если архитектурной поддержки не требуется, почему не компилируется например под ARM с помощью gcc на x86? Для чего вообще компилятору указывается ABI?
Почему нонсенс, Вы же говорите под какую платформу хотите собрать, ну а если для Вас уже кто то сделал все остальное, то поверьте это не значит что компилятор языка ничего не знает об архитектуре под которую генериться код.
Не очень понимаю как это делает язык Си безопаснее. Но систему в целом это делает безопаснее, что в конечном итоге и требуется!
Я бы не разбрасывался словами, А более четко формулировал бы свои мысли. Изначально претензия была к формулировке, о том что язык ничего не знает про стек. Я утверждаю, что знает! Поскольку выделение переменной на стеке имеет локальную область видимости, и передача ссылки на эту переменную умирает при выходе из функции, как было показано в одном из коментариев о преимуществах языка rust.
А вот Ваша фраза
Как минимум не логична, поскольку связь со стеком, не означает, что можно им управлять и уж никак не означает, что таким образом можно встроенными средствами управлять переключением контекста.
mayorovp
Очень просто: студия при сборке бинарей под Linux использует gcc либо clang вместо родного cl.exe. Потому что cl.exe, внезапно, совсем не умеет создавать бинарники под linux, даже если там такой же amd64 что и на винде...
0xd34df00d
Реализация, на каждый, эээ, стекфрейм (если выражаться в привычных терминах) выделяющая память из кучи при входе в функцию и удаляющая память при выходе, будет соответствовать стандарту С, но стека в смысле вот этой вот непрерывной растущей области с локальными переменными у неё не будет.
abondarev Автор
Конечно. Правда нужно еще хранить где то указатели на стекфреймы, но это мелочи.
Я имел в виду, что есть разница в реальных компиляторах ( про которые не стоит забывать) при реализации: глобальных переменных, локальных переменных, статических локальных переменных, переменных выделенных на куче.
А так, конечно согласен, стек (и отсюда почему большинство языков реализуют именно такую структуру) это только очень удобная реализация конкреной идеи распределения переменных и регистров. Но так как компилятор должен знать как устроена организация его локальных переменных, то я и написал, что это преувеличение.
anatolymik
Не удивительно что портирование было настолько трудным. Титаническая работа. Намного сложнее чем делать самому.
Я с самого начала сказал что язык Си, а не его компилятор. Это называется переобуваться в воздухе.
abondarev Автор
И, если бы автор оригинального коммента, написал, как Вы, что имеется в виду стандарт языка Си, а не фразы типа
То никакого треша в комментах конечно бы не было!
А так он понес прекрасную фигню, что компилятор не должен ничего знать об архитектуре процессора… Надеюсь он имел в виду, что используется промежуточный код типа llvm, но без этих пояснений, выглядит странно.
anatolymik
А что? Разве должен? Блин, а я не знал. Спасибо что просветили.
А че такое промежуточный код?
Starl1ght
Мы пишем драйвер на C++ (внезапно, даже 17). Да, у нас нет стандартной библиотеки, но тупо из-за наличия деструкторов в языке и инкапсуляции — разработка упрощается на порядки, никакие ресурсы не текут. Я не вижу смысла писать на чистом С вообще в любой разработке — даже крошечный сабсет С++98 выигрывает у чистого С по всем возможным статам (ну, кроме вероятного отсутствия компилятора под какой-нибудь некроконтроллер).
Siemargl
Ну про С++98 это перебор — на нем очень неудобно писать с STL (а без нее опять сырые указатели итп), а вот с++11/14 +линтер уже вполне безопасен и удобен по сравнению с другими условно безопасными языками.
Единственный слаборешенный вопрос был с глобальной оптимизацией при наличии исключений, который привел в итоге к noexcept.
Ну еще спорная производительность ARC, которая впрочем обходится минимизацией использования кучи.
Впрочем последние две темы настолько тонкие, что в большинстве языков до обсуждения такого дело и не доходит — есть проблемы покрупнее =)
Starl1ght
В конкретно моем случае (полное отсутствие стандартной библиотеки в кернеле) — мы написали свои строки\умные указатели и тд и тп.
abondarev Автор
Речь шла о замене С/С++.
С++ не используется в надежном ПО, не потому что нет компиляторов, а потому что менее предсказуемо, и можно уйти в область, смотри как я могу. Берем например стандарт MISRA. там вводятся различного рода ограничения на сложные конструкции. Программировать безусловно становиться тяжелее, но вот код более поддерживаемый и понятный, следовательно надежный.
Вот Вам пришлось написать стандартную библиотеку (или какие то ее части), а кто сказал что там нет ошибок? Анализаторы кода стаонвятся сложнее, если использовать хитурые конструкции и так далее. А так да, на чем писать дело вкуса, и 17 плюсы (да и не только 17) конечно добавляют возможностей для разработчика по сравнению с чистым Си.
Parondzhanov
abondarev затронул важную проблему. Существует потребность в безопасных языках. Язык ДРАКОН — попытка создать безопасный визуальный язык.
На практике используется, в частности, гибридный язык Дракон-Си, где Си служит целевым языком. При этом си-код не пишут вручную; он формируется автоматически на выходе дракон-схемы (комплекта дракон-схем). Вероятность ошибки уменьшается или сводится к нулю.
Цель языка ДРАКОН — обеспечить безопасность потока управления.
anatolymik писал:
Разница в том, что на ДРАКОНе ошибок будет меньше или не будет совсем.
Сергей Ефанов поясняет:
anatolymik писал:
Вероятность того, что вы на входе (т.е. в дракон-схеме) зададите неправильно, очень мала. потому что ДРАКОН срывает с ошибок «шапку-невидимку». Ошибки «сами лезут в глаза», поэтому пользователь (с большой вероятностью) их не сделает. На это есть две причины.
1) дракон-схема строится по правилам когнитивной эргономики, которая обнажает ошибки или лишает пользователя возможности сделать ошибку.
2) Графика дракон-схемы формируется программой дракон-конструктор, на основе визуального логического исчисления по правилам визуального логического вывода.
Это значит, что (во избежание ошибок) пользователю языка ДРАКОН запрещено проводить линии между иконами дракон-схемы. Все линии автоматически проводит дракон-конструктор, а пользователь лишь управляет этим процессом, указывая какую икону (или макроикону) выбрать и в какую валентную точку ее вставить. Это вкратце.
Разумеется, записывая текст внутри иконы, пользователь может ошибиться, но это будет ошибка ЛИНЕЙНОГО участка, которую сравнительно легко можно выявить и устранить.
anatolymik
Очень интересная форма высказывания. Сначала вы написали этот комментарий выше, потом удалили. Сейчас написали все тоже самое что было там. Вряд ли так можно заинтересовать.
taujavarob
Это старинная известная технология.
Берутся типа «лучшие практики» и «рисование схемы» по которой и генерируется программа, использующая эти «лучшие практики».
В Java это, к примеру — Eclipse Modeling Framework (EMF) (Не взлетел, но кто-то юзает).