Недавно (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 может дать свои плоды, правда, должно пройти немало времени.

Заключение


Как я уже сказал во введении, данная конференция позволяет делиться идеями, обсуждать и дискутировать. По многим вопросам были представлены несколько подходов, например, про модульное ПО и безопасное ПО. Причем организаторы конференции сознательно зовут докладчиков с разными подходами и это делает конференцию еще более интересной. Ну и конечно, конференция очень открытая, как сказал Дмитрий Завалишин в ходе дискуссии об языке Си, “Пять минут славы каждому“.

P.S.


Только что прочитал статью на хабре под названием “ Технические СМИ как базар”. В ней объясняется, как важно иметь несколько различных мнений. Предлагаю продолжить дискуссию о языке Си на Хабре. Например, очень интересно узнать, есть ли кросс-платформенные промышленные решения на rust или go?

Комментарии (306)


  1. lamerok
    25.06.2019 16:36
    +2

    Основная проблема Си есть его же преимущество:

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

    — он требует очень внимательного отношения к разработке софта, очень легко сделать функциональные ошибки, которые трудно отловить по причине этого полного контроля со стороны программиста. Т.е. грубо говоря, программист и есть слабое звено тут, причем в языке Си это особенно часто проявляется.
    использовать кучу уже разработанного ПО на языке Си, поскольку оно гораздо надежнее и более отлаженное

    Согласен отчасти, много софта есть которое временем проверено. Но возьмем HAL для Stm, сколько люди его пользуют? А баги приводящие к отказу где-нить на трубопроводе на каком-нибудь автомате до сих пор люди ловят, да что там HAL, заголовочники на Си для микроконтроллеров, написанные производителем содержат ошибки (например по выравниванию структур). Конечно есть много сертифицированных Сишных библиотек к ним доверия больше, но бывают случаи даже SIL3 операционки выдают такие фокусы из-за макроса… Правда надо сказать, что большинство таких сертификатов получается за «Проверенно временем»
    GCC кстати не рекомендован для использования при разработке надежного софта.


    1. abondarev Автор
      25.06.2019 16:45

      Основная проблема Си есть его же преимущество

      Абсолютно согласен! Но подразумевается что при написании ядра ОС, ну внимательнее разработчики должны что ли быть :) А взять например язык более высокого уровня, кто сказал что разработчики компилятора или рантайма (виртуальной машины) не сделают ошибку?

      Но возьмем HAL для Stm, сколько люди его пользуют? А баги приводящие к отказу где-нить на трубопроводе на каком-нибудь автомате до сих пор люди ловят, да что там HAL, заголовочники на Си для микроконтроллеров, написанные производителем содержат ошибки (например по выравниванию структур)

      На мой взгляд HAL для stm ок относительно свежий, врядли можно сравнивать с Unix или теми же Виндами, там проверка временем и количеством использования сильно больше!

      Правда надо сказать, что большинство таких сертификатов получается за «Проверенно временем»

      Так может это и есть правильный подход? :)


    1. TonyLorencio
      25.06.2019 17:12
      +1

      GCC кстати не рекомендован для использования при разработке надежного софта.

      А что рекомендуют и обычно используют?


      1. hhba
        25.06.2019 17:28

        То, на что есть соответствующие сертификаты. Например, если вы сертифицируете свои разработки под 50128, то у вас емнип нет альтернатив к iar c compiler (это из популярных).


        1. lamerok
          25.06.2019 17:30

          GreenHills, IAR 8.22 только тот, что с сертификатом.


          1. hhba
            26.06.2019 16:10

            Мне казалось, что у GHS нет сертификата для 50128. Впрочем у них достаточно других сертификатов.

            UPD: Да, где были мои глаза — есть!


      1. lamerok
        25.06.2019 17:58

        GreenHills, и IAR 8.22.3 только тот, что с сертификатом.


    1. hhba
      25.06.2019 17:30

      Вот тут я не понял. Как смена языка (с Си на Раст например) спасет вас от грубых ошибок производителя в msp/bsp?


      1. lamerok
        25.06.2019 17:55

        Если производитель, например, будет заголовочники предоставлять не на Си, а на С++, то можно избежать всякой ерунды…
        Ну вот пример, STM предоставила flashloader для IAR… Если что файл лежит тут для IAR 8.20
        EmbeddedWorkbench8.1\arm\src\flashloader\ST\FlashSTM32F4xx\inc:

        Заголовок спойлера
        typedef struct
        {
          __IO uint16_t SR;         /*!< USART Status register,  Address offset: 0x00 */
          uint16_t      RESERVED0;  /*!< Reserved, 0x02                     */
          __IO uint16_t DR;         /*!< USART Data register,  Address offset: 0x04 */
          uint16_t      RESERVED1;  /*!< Reserved, 0x06              */
          __IO uint16_t BRR;        /*!< USART Baud rate register,  Address offset: 0x08 */
          uint16_t      RESERVED2;  /*!< Reserved, 0x0A                                                */
          __IO uint16_t CR1;        /*!< USART Control register 1,  Address offset: 0x0C */
          uint16_t      RESERVED3;  /*!< Reserved, 0x0E                                                */
          __IO uint16_t CR2;        /*!< USART Control register 2,  Address offset: 0x10 */
          uint16_t      RESERVED4;  /*!< Reserved, 0x12                                                */
          __IO uint16_t CR3;        /*!< USART Control register 3,  Address offset: 0x14 */
          uint16_t      RESERVED5;  /*!< Reserved, 0x16                                                */
          __IO uint16_t GTPR;       /*!< USART Guard time and prescaler register, Address offset: 0x18 */
          uint16_t      RESERVED6;  /*!< Reserved, 0x1A                            */
        } USART_TypeDef;


        1. Alexey_Alive
          25.06.2019 18:52
          +1

          На чистом Си тоже есть static_assert прямой в стандарте (_Static_assert). Для выравнивания есть оператор offsetof, правда нет нормальной стандартной реализации, но огромное количество компиляторов поддерживают его с помощью builtin.


          1. lamerok
            25.06.2019 18:55

            Ага, видимо заголовочники писались до С11 стандарта


          1. Ryppka
            26.06.2019 13:20

            А в C99 можно получить тот же эффект с помощью умело написанного enum.


        1. mayorovp
          25.06.2019 23:00

          Хм, а что за случаи такие хитрые? Вроде бы тут выравнивания не должно появиться…
          Или его макрос __IO добавляет?


          1. lamerok
            26.06.2019 00:36

            Общий случай, выравнивание по 4 байта, идет 16 битный инт, потом дырка в 2 байта, потом 16 битный инт RESERVED, потом дырка в 2 байта. И компилятор имеет на это полное право, он же не обязан за вас додумывать, что вы хотите два 16 битных инта запихать в одну ячейку памяти 32 битную и в итоге сделает размер этой структуры в 2 раза больше ожидаемого и адреса регистров не те, что ожидает программист. Компиляторы конечно не такие тупые, чтобы дырки всавлять, но в общем случае они должны это сделать исходя из архитектуры микропроцессора. Любой статический анализатор кода руганется жестко с сообщение уровня Ошибка.
            _IO это volatile.


            1. KanuTaH
              26.06.2019 03:25
              +1

              Ну право-то он имеет, согласен (чтобы не имел, нужен __attribute__(packed)). Но обычно компиляторы выравнивают поля структур на их размер, то есть char'ы выравниваются побайтно, int16 на 2 байта, int32 — на 4 байта. То есть могут быть дырки в промежутках между char и int16 или int16 и int32, но не между полями одинакового размера (если их, конечно, не выравнивают специально каким-то нестандартным образом через соответствующий атрибут).


              1. lamerok
                26.06.2019 11:46

                Да это скорее всего так для 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.


                1. KanuTaH
                  26.06.2019 12:19

                  Ну все зависит от этих requirements. Теоретически можно представить себе архитектуру, которая будет требовать выравнивать int16 по 32-битной границе, но лично я такую безумную архитектуру сходу назвать затрудняюсь.


            1. Ryppka
              26.06.2019 13:25

              А что, адреса 16-битных регистров ввода-вывода выровнены по границам 2 байт?


              1. lamerok
                26.06.2019 14:12

                Как же они 16 битные, когда архитектура 32 бита. Они 32 битные, просто старшие 16 бит не используются…
                image


                1. Ryppka
                  26.06.2019 14:17

                  И какой же вывод? Каковы адрес и смещение относительно базы рассматриваемого 16-битного регистра? Каковы адрес и смещение относительно базы следующего поля? Не на тот ли самый слоп больше?


                  1. lamerok
                    26.06.2019 14:32

                    вывод такой, мы не можем гарантировать, что компилятор сделает то, что мы задумали и не вставит дырки, и поэтому такую структуру без выравнивания использовать нельзя… и надо бы её переделать для данного микроконтроллера вот в такую:

                    struct Uart
                    {
                      __IO uint32_t SR;         
                      __IO uint32_t DR;         
                    .
                    .
                    .
                    }
                    


                    1. KanuTaH
                      26.06.2019 14:42

                      Лучше явно указать компилятору необходимость упаковки структуры с помощью соответствующей прагмы или атрибута. Ваш вариант тоже ничего не гарантирует в общем случае, компилятор все еще волен делать любые padding'и, только уже между int32-полями :) На самом деле это обязательно нужно делать при написании переносимого кода, для работы которого важны смещения внутри структур, но если код де-факто не будет переносимым (предполагается работа на конкретной архитектуре и сборка конкретным компилятором), то этим часто пренебрегают.


                      1. lamerok
                        26.06.2019 15:00

                        Нет для 32 битной машины выравнивание по умолчанию 4. считайте стоит pragma(4). Прагма непереносимый код, поэтому не надо её использовать. А гарантировать можно с помощью static_assert. Если вдруг этот код будете запускать на 64 битной машине, он вывалится с ошибкой… Но если уж вы хотите переносить на все типы машин, то тогда нужно делать, что-то типа этого:

                        template <unsigned int sz>
                        struct Register_traits { };
                        
                        template <>
                        struct RegisterTraits<8>  { using internal_type = std::uint8_t; };
                        
                        template <>
                        struct RegisterTraits<16> { using internal_type = std::uint16_t };
                        
                        template <>
                        struct RegisterTraits<32> { using internal_type = std::uint32_t; };
                        
                        template <>
                        struct RegisterTraits<64> { using internal_type = std::uint64_t; };
                        //Где-нибудь в отдельном h файле, для конкретной 32 битной машины или через #ifdefine определить тип так: 
                        using tRegisterType = RegisterTraits<32> 
                        //А потом так вот юзать...
                        struct Uart
                        {
                          __IO tRegisterType SR;         
                          __IO tRegisterType DR;         
                        .
                        .
                        .
                        }
                        static_assert(sizeof(Uart) == sizeof(tRegisterType) * 14);
                        

                        Но если совсем нет доверия, то лучше тогда вообще такие структуры не использовать и напрямую с адресами регистров работать типа такого:
                        Register<32, readOnly> Usart1Sr   { 0x40021000 };
                        Usart1Sr = 2; // ошибка компиляции, регистр только для чтения
                        uint32_t value = static_cast<uint32_t>(Usart1Sr) ; //Ок, 
                        

                        Вот тут можно почитать


                        1. KanuTaH
                          26.06.2019 15:08

                          Нет для 32 битной машины выравнивание по умолчанию 4

                          Ну если что-то такое считается «по умолчанию», то код по определению непереносимый :) Типа рассчитан на нормальную работу только на 32-битной архитектуре.

                          Прагма непереносимый код, поэтому не надо её использовать.

                          Если есть уверенность, что компиляторы и кросс-компиляторы для целевых архитектур ее поддерживают, то ее вполне можно использовать (для надежности добавив проверку размера структуры через static assert). Потому что это удобно. Подавляющее большинство мейнстримовых компиляторов (в том числе IAR) в нее умеют. Если такой уверенности нет, то тогда да, скорее всего придется работать напрямую с адресами регистров.


                        1. hhba
                          26.06.2019 17:20

                          лучше тогда вообще такие структуры не использовать и напрямую с адресами регистров работать типа такого


                          Что, внезапно, еще более общО и переносимо.


                    1. Ryppka
                      26.06.2019 15:10

                      Гарантировать нечего: компилятор не вставит дырки только если это указано в его настройках или параметрах вызова. Покажите пример, где эту структуру размещают в памяти. И пример, где наличие слопа приводит к проблемам, но в реально работающим коде, а не в выдуманном…


                      1. lamerok
                        26.06.2019 16:11

                        Я не могу привести код, потому что текущий 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 эти заголовочники поправили…

                        Новые заголовочники
                        typedef struct
                        {
                          __IO uint32_t SR;         /*!< USART Status register,                   Address offset: 0x00 */
                          __IO uint32_t DR;         /*!< USART Data register,                     Address offset: 0x04 */
                          __IO uint32_t BRR;        /*!< USART Baud rate register,                Address offset: 0x08 */
                          __IO uint32_t CR1;        /*!< USART Control register 1,                Address offset: 0x0C */
                          __IO uint32_t CR2;        /*!< USART Control register 2,                Address offset: 0x10 */
                          __IO uint32_t CR3;        /*!< USART Control register 3,                Address offset: 0x14 */
                          __IO uint32_t GTPR;       /*!< USART Guard time and prescaler register, Address offset: 0x18 */
                        } USART_TypeDef;


                        1. Ryppka
                          26.06.2019 17:29

                          Представленные структуры в плане смещения от начала структуры значимых полей идентичны. Вы пишете в регистр 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 без приведения типа.


                          1. hhba
                            26.06.2019 18:13

                            Может проще объявлять все регистры 32-битными, каковыми они и являются? Всегда лучше быть честным, чем умным.

                            Впрочем и это не снимает полностью вопрос переносимости.


                            1. Ryppka
                              27.06.2019 08:56

                              А они, регистры, 32-битные? На железе?
                              Адреса MMIO регистров 32-битные, а регистры на железе могут быть и 8-, и 16-, и 32-, и, подозреваю, даже 64-битными. В языке C, а вслед за ним в C++ это явно не выражается, по крайней мере пока: ISO/IEC TR 18037 висит непринятым, хотя нужен не только во встроенных системах.
                              Вот и получается разной степени костыльные решения для того, чтобы сделать адреса 16-битных регистров правильно расположенными относительно базового адреса в ситуации, когда адреса регистра должны начинаться по границе 4 байт, а выравнивание 16-битного поля структуры по умолчанию — 2 байта. Или все прятать за кучей неприглядных макросов/инлайн-функций. Или как-то совмещать эти методы.
                              Что до переносимости, то сила C именно в том, что можно сделать непереносимые решения, там и когда это нужно. Чем ближе к железу, тем меньше переносимости и больше трюков, расширений компилятора и т.д.
                              В силу изложенного не могу сказать, что решение инженетов STMicro чем-то хуже или лучше, чем обмазывания 4-х записей в регистры кучей std::enable_if.


                              1. hhba
                                27.06.2019 09:18

                                А они, регистры, 32-битные? На железе?


                                Могу ошибаться, но по-моему конкретно эти регистры 32-битные заложены в железе (а не просто отображены как 32-битные), по крайней мере обратное не указано явно.

                                регистры на железе могут быть и 8-, и 16-, и 32-, и, подозреваю, даже 64-битными


                                Абсолютно любыми, зависит от железа. И когда у меня, например, в контроллере были некоторые регистры 8-битные, а некоторые 16-битные, то я предпочитал 16-битные адресовать половинками, для уверенности (сей подход не рекламирую). Правда там все равно шина данных была 8-битная и регистры физически на ней стояли, так что своя кухня в некотором роде.

                                ISO/IEC TR 18037


                                Как интересно, ничего не знал об этом стандарте… Интересно, что в нем планируется внедрить, и как это увяжется с существующим развитием языка.

                                Вот и получается разной степени костыльные решения для того, чтобы сделать адреса 16-битных регистров правильно расположенными относительно базового адреса в ситуации, когда адреса регистра должны начинаться по границе 4 байт, а выравнивание 16-битного поля структуры по умолчанию — 2 байта


                                И это адище какое-то. Если вдруг вам понадобится 8-битный регистр среди кучи других регистров, то потребуется за ним гуськом расположить три таких же поля… И строго, очень строго следить за тем, чтобы кто-нибудь где-то в топе модуля не вписал pragma pack (2) например.

                                В этом смысле я считаю более консистентным подход с отдельным доступом к отдельным регистрам через указатели. Это правда требует больше работы с прямыми адресами, что само по себе не очень хорошо.

                                Что до переносимости, то сила C именно в том, что можно сделать непереносимые решения, там и когда это нужно


                                С этим не спорю.


                                1. Ryppka
                                  27.06.2019 09:21

                                  И это адище какое-то.

                                  Добро пожаловать в реальный мир низкоуровневого программирования)))


                                  1. hhba
                                    27.06.2019 09:27

                                    Добро пожаловать в реальный мир низкоуровневого программирования)))


                                    Вы так говорите, будто я не живу в этом мире с самого института ))


                                1. Ryppka
                                  27.06.2019 09:27

                                  Могу ошибаться, но по-моему конкретно эти регистры 32-битные заложены в железе (а не просто отображены как 32-битные), по крайней мере обратное не указано явно.

                                  Тоже могу ошибаться, но на железе они вроде бы могут быть 16-битными, а могут быть и 32-битными. В конкретной аппаратной реализации они 16-битные, поэтому старшее слово в 32-битных (с точки зрения memory map) регистрах зарезервировано. Адреса этих регистров да, будут кратны 4 байтам. И если убрать тот или иной способ указать реальное выравнивание 16-битных uint16_t volatile xx, то будет запись/чтение зарезервированной части регистра с понятными последствиями. На сегодняшний день я не знаю красивого и эффективного решения подобных проблем.


                                  1. hhba
                                    27.06.2019 09:49

                                    В конкретной аппаратной реализации они 16-битные, поэтому старшее слово в 32-битных (с точки зрения memory map) регистрах зарезервировано


                                    Простите, а вы это знаете, или предполагаете?

                                    Простой пример из практики: CPLD-сателлит у процессора, внутри нее есть набор 32-битных регистров, у большинства из которых доступна для использования только младшая половина, остальное зарезервировано (физически туда писать можно, ничего страшного не произойдет, просто смысла нет). В документации, как и полагается, старшее слово обозначено как reserved, однако регистр от этого 16-битным не становится. Конечно в микроконтроллере ситуация чуть иная, и скорее всего неиспользуемые регистры (которые будут только место занимать) физически отсутствуют, однако это не мешает адресным дешифраторам прикидываться валенком.

                                    И если убрать тот или иной способ указать реальное выравнивание 16-битных uint16_t volatile xx, то будет запись/чтение зарезервированной части регистра с понятными последствиями. На сегодняшний день я не знаю красивого и эффективного решения подобных проблем.


                                    Если мы используем структуру для доступа к регистрам — то да, суровое танго.


                                    1. Ryppka
                                      27.06.2019 09:58

                                      Простите, а вы это знаете, или предполагаете?

                                      Как там конкретно в железе даже не задумывался. Я знаю, что «работает» только изменение младших 16 бит по адресу 32-битного целого и что если объявить этот адрес адресом 16-битного целого — то это будет работать.
                                      А вот можно ли без неприятных последствий записать по этому адресу 32-битное целое с мусором в старшем слове — не проверял. И не очень-то хочется.


                    1. hhba
                      26.06.2019 17:18

                      Вот именно! То есть проблема уже на уровне описания регистров, буквально в голове у писавшего.


        1. AVI-crak
          26.06.2019 00:21

          Какое там выравнивание? Адрес структуры напрямую прописан, его можно принять и передать — но не изменить.


          1. lamerok
            26.06.2019 00:38

            Выравнивание по полям структуры 16 битный int выравнивается на 4 байта, ячейки памяти то 32 битные, на не 16.


            1. AVI-crak
              26.06.2019 02:10
              -2

              Ну не может uint16_t в структуре с фиксированным адресом внезапно занять 4 байта, typedef мешает.
              А вот в новой структуре созданной например так:
              USART_TypeDef new_usart;
              размер переменных может быть увеличен в угоду ускорения общего алгоритма. Но для этого ещё постараться надо.


              1. lamerok
                26.06.2019 11:43

                Просто чтобы не лезть в дебри, читаем документацию на компилятор:
                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.


                1. AVI-crak
                  27.06.2019 14:11
                  -1

                  Просто чтобы не лезть в дебри

                  Читайте внимательнее!!! Сказано о структуре созданной пользователем, когда адрес структуры выбирает компилятор.
                  Фиксированный адрес + typedef — запрещает всякую самодеятельность компилятору. Адреса всех элементов структуры, а также их размеры — известны ещё до начала компиляции. Выравнивание не выполняется.


                  1. mayorovp
                    27.06.2019 14:22

                    Смотрите. Допустим, у нас есть две одинаковые структуры, одна по фиксированному адресу, вторая по выбранному компилятором. Мы копируем одну структуру в другую через memcpy. Что должно получиться?


        1. LeonidPr
          26.06.2019 12:30

          А там нигде в начале файла нет: #pragma pack(1)?
          Который просто на весь файл распространяется.


          1. lamerok
            26.06.2019 14:13

            Посмотрел, нету…


          1. hhba
            26.06.2019 17:15

            То же самое предположил. Иначе как оно работает? Разве что на самом деле потом никак не используется…


        1. hhba
          26.06.2019 17:14

          Ну стоп, а в чем проблема-то? Ну оказались поля на самом деле по четыре байта, а не по два, кому от этого плохо? Аааа, кажется я догадываюсь… Наверное кто-то потом решил, что эта структура в памяти расположена сплошняком без промежутков между полями, и значит можно с ней работать как с массивом? Ну так ССЗБ, не?

          Вообще пример конечно красивый, тут вам не откажешь, прямо руки тянутся… Но нет, слишком плохо я знаю плюсы. И я такой не один!


          1. mayorovp
            26.06.2019 17:35

            Судя по volatile-полям, один из экземпляров этой структуры располагается в памяти по фиксированному адресу, и должен этими самыми volatile-полями накрывать отображенные в память порты ввода-вывода.


            1. hhba
              26.06.2019 18:00

              Да, я понял, про то и пишу — воспринимать эту структуру как линейный массив (чего угодно, в том числе регистров) в общем случае нельзя. И хотя это очень распространенный прием (и от него трудно убежать — например я из-за лени использую STM HAL и пожинаю сопутствующие плоды), но мне он очень не нравится, поскольку опускает нас с уровня языка на уровень понимания его трансляции. Отсюда все эти сакральные знания про gcc aligned и ему подобное.

              Добавлю, что дело не только в необходимости держать в голове выравнивание, нужно еще как-то защититься от случайных ошибок вида «вставили поле, не подумав про смещения». Я это встречал, и после такого вся красота использования структур для отображения регистров теряется.


              1. Ryppka
                27.06.2019 08:57

                В анализе и высказываниях по поводу этой структуры неплохо учитывать реальные требования к выравниванию полей структур и адресов MMIO.


                1. hhba
                  27.06.2019 09:21

                  В анализе и высказываниях по поводу этой структуры неплохо учитывать реальные требования к выравниванию полей структур и адресов MMIO


                  Не неплохо, а необходимо. Либо можно просто отказаться от использования структур для доступа к группам регистров (но здесь есть свои минусы).


  1. amartology
    25.06.2019 17:00
    +1

    Коллеги показали работу не только на отечественных Эльбрусе и Байкале, но и, например, на такой относительно редкой архитектуре как RISC-V.
    RISC-V — не «относительно редкая» архитектура, а «самая быстрорастущая». Ей только в России уже не меньше трех компаний занимается, а в мире так и вовсе уже счет за сотню дизайнов ушел, включая таких монстров, как Nvidia и Western Digital.


    1. abondarev Автор
      25.06.2019 17:10
      +1

      Все таки относительно редкой, поскольку довольно новая.
      Безусловно перспективная, согласен самая быстрорастущая, но посмотрите например сколько дистрибутивов Linux поддерживает ARM и MIPS, а сколько RISC-V? До недавнего времени, это было скорее встроенное решение на основе ядер ПЛИС.


  1. torgeek
    25.06.2019 17:06

    Вопрос про использование 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.


    1. abondarev Автор
      25.06.2019 17:18

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

      Он безусловно растет, но я лично о нем уже лет 5 назад слышал. И задавали все тот же вопрос, почему не на rust? Он такой хороший надежный, решает много очевидных проблем Си. Но когда речь заходила, а почему сами не используете, тут же «у нас продакшен мы не может экспериментировать». :)


      1. TargetSan
        26.06.2019 12:05

        Как по мне, в этом и проблема. Все ждут пока кто-нибудь другой вложится в поддержку архитектуры или тулчейна. Никто не хочет инвестировать ресурсы, даже крупные компании. Получается замкнутый круг.


        1. abondarev Автор
          26.06.2019 12:09

          Ну почему же никто. Если бы не вкладывались, хотя бы на уровне исследований, то врядли бы и до такого уровня rust бы дорос. Вкладываются и довольно много, но вот почему он не выходит прямо в массы это вопрос.


          1. TargetSan
            26.06.2019 12:13

            Я конкретно про embedded. Пока кроме проектов Japaric и ведомой им embedded working group не видно ничего. Думаю, если сравнить с тем, сколько вкладывается в поддержку С в тулчейнах, разница будет порядка на 3. Если не больше.


            1. Halt
              26.06.2019 12:35

              В смысле никого? www.tockos.org


              1. TargetSan
                26.06.2019 12:53

                Я не вижу там в контрибьюторах хоть какие-то коммерческие компании. Подобный проект — это замечательно. Но он хорошо иллюстрирует проблему во многих областях. Ниша нарастила определённую массу, стабилизировалась и "окуклилась". С одной стороны — много зрелых инструментов. С другой — для захода в нишу жизненно необходимо интегрироваться с тем, что есть — C-based тулчейнами.


            1. abondarev Автор
              26.06.2019 12:43

              Думаю, если сравнить с тем, сколько вкладывается в поддержку С в тулчейнах, разница будет порядка на 3. Если не больше.

              Думаю сильно больше. Но не стоит забывать, что коммерческие компании должны еще и прибыль генерить, в Си огромная готовая инфраструктура, в которую ты вкладываешь и используешь кучу готового. В Rust пока такого нет, точнее это не сопоставимо по объемам. Поэтому пока в основном на уровне исследований вложения идут. Взять производителей микроконтроллеров, они взяли выпустили чип со стандартной архитектурой (могут не вкладываться в компилятор), написали драйвера для переферии и все можно выпускать, есть уже куча rtos, ide, средств разработки, библиотк, и т.д. Разработчикам готовых устройст это выгодно, вышел дешевый чип, и можно сразу начинать производство железки, ведь и программисты готовые есть.


              1. TargetSan
                26.06.2019 12:54

                Я об этом и говорю. Требуется преодолеть гигантскую инерцию.


    1. Labunsky
      26.06.2019 18:13
      +1

      После си переходить на раст больно. Язык содержит в себе гору клевых идей, но синтаксис явно разрабатывался в первую очередь для чтения компилятором, а уже потом человеком. И вечное желание сделать его максимально не С-подобным не помогает(


      1. torgeek
        27.06.2019 11:09

        Про синтаксис – это вечная американская боль. В штатах языки патентуются и для каждого нового приходится изголятся в названиях ключевых слов и описании синтаксиса, что бы не попасть на судебный иск от разработчиков других языков. В Европе всё проще, а в России так вообще спокойно – прямой законодательный запрет на патентование языков и алгоритмов.

        А можно пару примеров, что в синтаксическом новоязе Rust так сильно причиняет боль?


        1. Labunsky
          27.06.2019 13:25

          вечная американская боль

          Всякие си с плюсами и даже корпоративной джавой уживаются как-то, хотя я не эксперт в этих вопросах


          А можно пару примеров, что в синтаксическом новоязе Rust так сильно причиняет боль?

          Все перечислять не буду, можно на примере самых основных. Для обозначения переменной нужно два ключевых слова let mut, аналогично его должны иметь модифицируемые параметры функций. Примитивы все имеют явную разрядность, которую приходится держать в голове (неявного каста тут нет), даже если это не нужно. Функции надо помечать ключевым словом, при этом все равно явно задавая возвращаемый тип. Каждый match (здешний switch) должен обрабатывать все возможные области значений, необходимо таскать с собой пустую строку дефолта _ => {}. При создании лямбд у разработчиков сломались клавиши скобок: let closure = |i: i32| -> i32 { i + 1 };. Возвращение значений из функций может быть явным и не- (просто последнее выражение без ;), но выражения уже не умеют в return. Из-за этого, кстати, код труднее не писать, но читать — без цветной пометки эти строчки на раз пропускаются, либо вводят в смущение. И, да, выражения теперь возвращают значения, поэтому в чужом коде можно ожидать конструкций из серии:


          // "умная" инициализация
          let mut x = if a {
              // сотня строк кода
              0
          } else if b {
              // снова куча логики
              5
          } else {
              // еще две сотни
              1
          }
          ...
          match x {
              // и фиг его знает, на самом деле, куда он тут попадет
          }

          Это все только поверхостные мелочи. Но при каждом переходе между ним и другим языком бросаются в глаза. Что хуже, вместе выражаются в очень загруженный код (примеры есть тут в комментариях), в котором даже с умным парсером и подсветкой (они никак не подскажут значения x в коде выше, потому что тот не участвует в выражениях) без поллитры не всегда разобраться


          1. Ryppka
            27.06.2019 13:35

            Единственное, с чем частично соглашусь — неявный возврат. А все остальное — дело привычки или вкусовщина. По мне так нормально, если не нравится — идем в другой общепит.


            1. Labunsky
              27.06.2019 14:09

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


              1. PsyHaSTe
                27.06.2019 14:15

                Потому что портить язык вредными конструкциями только чтобы сделать его более знакомым тем, кто по этим граблям походил — плохое занятие. http://www.informit.com/articles/article.aspx?p=2425867 здесь неплохо раскзаано, почему и неявные касты плохо, и тип впереди функции, и многое-многое другое.


                1. Labunsky
                  27.06.2019 14:23
                  -1

                  Ох уж эти глупые доктора наук Ритчи и Керниган, а потом еще и Страуструпы всякие, нагородили таких вредные конструкций, что до сих пор разгребаем, но не разгребем


                  неплохо раскзаано, почему и неявные касты плохо, и тип впереди функции, и многое-многое другое

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


                  1. PsyHaSTe
                    27.06.2019 14:33

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

                    А что, было бы плохо?


          1. PsyHaSTe
            27.06.2019 14:14
            +1

            Все перечислять не буду, можно на примере самых основных. Для обозначения переменной нужно два ключевых слова let mut,

            Неправда, достаточно let


            Примитивы все имеют явную разрядность, которую приходится держать в голове (неявного каста тут нет), даже если это не нужно.

            Да, помнить, что int на этой машине 2 байта, а на этой 4 намного удобнее. Или внезапно из сишки типа int32_t пропали.


            Функции надо помечать ключевым словом, при этом все равно явно задавая возвращаемый тип.

            Какие альтернативы предлагает? Очень надеюсь, не писать тип функции впереди?


            Каждый match (здешний switch) должен обрабатывать все возможные области значений, необходимо таскать с собой пустую строку дефолта _ => {}.

            Действительно, какая глупость.


            При создании лямбд у разработчиков сломались клавиши скобок: let closure = |i: i32| -> i32 { i + 1 };.

            let closure  = |i| i + 1;

            Возвращение значений из функций может быть явным и не- (просто последнее выражение без ;), но выражения уже не умеют в return.

            Вопрос привычки


            Это все только поверхостные мелочи. Но при каждом переходе между ним и другим языком бросаются в глаза. Что хуже, вместе выражаются в очень загруженный код (примеры есть тут в комментариях), в котором даже с умным парсером и подсветкой (они никак не подскажут значения x в коде выше, потому что тот не участвует в выражениях) без поллитры не всегда разобраться

            Ваша претензия по сути в том, что тут "не как в си". И слава богу.


            1. Labunsky
              27.06.2019 14:33

              Неправда, достаточно let

              Это будет не переменная, потому что ее нельзя будет переменить)


              Или внезапно из сишки типа int32_t пропали.

              Они существуют параллельно со встроенными типами данных для задач, в которых разрядность нужна явно (например, для сериализации). В остальных случаях рекомендуется использовать обычные типы данных, так как компилятор с их помощью будет генерировать более эффективный и независимый от платформы код


              Про лямбды — дело в | |. И да, если язык позиционируется как замена, то он должен обеспечивать простой переход, а не изобретать велосипеды на каждом углу


              1. PsyHaSTe
                27.06.2019 14:35

                Это будет не переменная, потому что ее нельзя будет переменить)

                Её и не надо менять в общем случае.


                Они существуют параллельно со встроенными типами данных для задач, в которых разрядность нужна явно (например, для сериализации). В остальных случаях рекомендуется использовать обычные типы данных, так как компилятор с их помощью будет генерировать более эффективный и независимый от платформы код

                Так он генерирует как раз зависимый код.


                Про лямбды — дело в | |. И да, если язык позиционируется как замена, то он должен обеспечивать простой переход, а не изобретать велосипеды на каждом углу

                Упростили парсер себе таким образом. В чем проблема-то?


                1. Labunsky
                  27.06.2019 15:24

                  Её и не надо менять в общем случае.

                  Это звучит очень странно, учитывая, что свойство буквально содержится в корне слова


                  Так он генерирует как раз зависимый код.

                  Неправильно выразился, сам код при написании будет меньше зависеть от платформы: какого бы размера int не был, он всегда будет целочисленным и знаковым, знания чего нам часто вполне достаточно


                  1. BlessMaster
                    27.06.2019 19:38

                    Это звучит очень странно, учитывая, что свойство буквально содержится в корне слова

                    Это не переменные, это — биндинги. В большинстве случаев переменные не нужны. Поэтому и let mut, чтобы ленивые люди предпочитали не использовать мутабельность там, где она не нужна.


                    К слову, в Rust вплоне можно перекрывать старое значение с тем же именем: let x = x + 1. Кроме того время жизни биндингов ограничено блоками, где они объявлены. И это тоже позволяет часто обходиться без мутабельности.


                    1. Labunsky
                      27.06.2019 19:42
                      -1

                      Ну так и я о том же говорю. Но на практике выражается в многословность


          1. TargetSan
            27.06.2019 20:32
            +3

            Для обозначения переменной нужно два ключевых слова let mut,

            Наконец-то с первого взгляда видно, что это переменная. Иммутабельность по умолчанию я считаю скорее плюсом.


            аналогично его должны иметь модифицируемые параметры функций.

            Это такой же байндинг. Было бы лучше иметь несколько разных правил?


            Примитивы все имеют явную разрядность, которую приходится держать в голове (неявного каста тут нет), даже если это не нужно.

            Единственное, что может быть немного неудобно — отсутствие неяного апкаста к более ёмкого типа. Хотя — вам не хватает неявного апкаста bool->int и неявного подсчёта хеша так, как вы не ожидали? Да, эта проблема встретилась мне в С++. Но ноги растут из С. По поводу явной разрядности — вы никогда не портировали программу с win16 на win32? С резким разрастанием размера int?


            Функции надо помечать ключевым словом, при этом все равно явно задавая возвращаемый тип.

            default int сами же авторы С посчитали очень плохой идеей. unit return же указывать необязательно. Про явное ключевое слово fn — вы соскучились по most vexing parse rule? Я — нет.


            Каждый match (здешний switch) должен обрабатывать все возможные области значений, необходимо таскать с собой пустую строку дефолта _ => {}.

            И это прекрасно, я считаю.


            При создании лямбд у разработчиков сломались клавиши скобок: let closure = |i: i32| -> i32 { i + 1 };.

            Здесь уже вкусовщина. Мне такой синтаксис кажется вполне имеющим право на жизнь.


            Возвращение значений из функций может быть явным и не- (просто последнее выражение без ;),

            Expression-based language. Особенность, которую надо знать.


            но выражения уже не умеют в return.

            Вы вполне можете использовать блок как часть выражения. И делать из него return.


            Из-за этого, кстати, код труднее не писать, но читать — без цветной пометки эти строчки на раз пропускаются, либо вводят в смущение.

            Неявный return да, может быть неудобен или непривычен. В целом же после небольшой практики и благодаря гораздо более мощному тайпчекеру перестаёт быть проблемой.


            В целом же, как человеку, пишущему на С++, мне ваши претензии кажутся сводящимися к "Этот язык не похож на привычный мне С". То, что множество языков скопировало этот синтаксис, не означает, что он лучший. Просто он более распространённый и привычный.


            1. Labunsky
              27.06.2019 20:45

              ваши претензии кажутся сводящимися к "Этот язык не похож на привычный мне С"

              Да ну я это не скрываю, первый же комментарий содержит аналогичную подстроку:


              И вечное желание сделать его максимально не С-подобным не помогает(


      1. PsyHaSTe
        27.06.2019 12:12

        Тоже хотел уточнить, что не так? Обычный МЛ-подобный синтаксис. Собственно из синтаксиса в си нормальные только скобочки, все остальное фигово — объявление функциональных аргументов, type first, вот это все.


      1. snuk182
        27.06.2019 12:56

        Попробуйте осилить синтаксис Nim — Rust после него покажется прогулкой в лесу под пение птиц :)


  1. amarao
    25.06.2019 17:38
    +1

    Аргумент про управление памятью — практически главный. Второй — это фиксированное ABI, с которым можно быть совместимым. (Для сравнения, с C++ ABI можно быть совместимым только при компиляторе той же версии, и удачном положении луны на небе).


    Однако, никто не упомянул слово Rust, который:
    а) Умеет ручное управление памятью и может генерировать код без рантайма (читай, эмбедд и ОС)
    б) умеет быть совместимым в обе стороны с С-ABI.


    И мне странно, потому что с точки зрения безопасности, разница между С и Rust, как между ездой на крыше синкансена и в его салоне.


    1. abondarev Автор
      25.06.2019 17:49

      И мне странно, потому что с точки зрения безопасности, разница между С и Rust, как между ездой на крыше синкансена и в его салоне.

      наверное соглашусь, хотя сам Rust не использовал.

      Но если упоминать
      а) Умеет ручное управление памятью и может генерировать код без рантайма (читай, эмбедд и ОС)
      б) умеет быть совместимым в обе стороны с С-ABI.


      то в чем же его преимущество? То есть будут дыры в Сишном коде, а хочется чтобы было всегда и везде!
      С другой стороны, это конечно уменьшение мест с потенциальными проблемами, но если посмотреть на это с той стороны, что существует уже много написаного и отлаженного кода и проверенных временем программ, то можно сказать, что это тоже путь к безопасности. Вы не согласны?


      1. amarao
        25.06.2019 17:55

        Ох, вы открываете гигантский топик.


        Совместимость с С-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.


        1. DSolodukhin
          25.06.2019 19:13
          +2

          В Раст есть unsafe (ключевое слово), которое отключает несколько важных проверок, так что наделать багов Си-уровня можно и в Rust.

          Unsafe в Rust по факту дает только одну новую возможность — разыменовывание сырых указателей (возможность вызывать код, написанный на С мы здесь не рассматриваем). При этом у вас остаются проверки связанные с заимствованием и владением, с конкурентным доступом к данным и пр. Поэтому наделать кровавого фарша как в С, с помощью unsafe сложно, разве что специально поставить перед собой такую задачу.


          1. humbug
            26.06.2019 10:12

            Вообще нет. unsafe так же даёт возможность работы с глобальными статическими переменными, реализовать unsafe impl (Sync). Так что им можно натворить кровавых вещей очень просто. И такие баги уже находили, хотя они жили в стд несколько лет, «проверенные временем».


            1. DSolodukhin
              26.06.2019 12:07

              В целом, я с вами согласен, но я бы не назвал приведенные вами примеры как «очень просто», это я как раз отношу к категории «специально поставить перед собой такую задачу».
              Изменяемые статические переменные — это вообще антипаттерн, если уж так хочется, стоит хорошо подумать, действительно ли оно вам надо, и если надо, то может быть стоит воспользоваться безопасными решениями? Тот же lazy_static + Mutex или RwLock. И unsafe не нужен и безопасный конкурентный доступ.


              1. snuk182
                27.06.2019 13:01

                Адресная арифметика тоже подпадает под unsafe. Каст нетолстых указателей (например, для реализации си-подобного наследования) туда же.


                1. mayorovp
                  27.06.2019 14:28

                  А зачем нужны адресная арифметика и си-подобное наследование?


                  1. snuk182
                    27.06.2019 14:40

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


                    1. mayorovp
                      27.06.2019 14:43

                      Я спрашивал не про наследование вообще, а про си-подобное наследование.


                      1. snuk182
                        27.06.2019 14:51

                        А разницы никакой. Это всего лишь единственно доступная в Rust на данный момент возможность реализации наследования — начинать структуры-наследники с общей структуры-базы.


                        1. mayorovp
                          27.06.2019 14:57

                          Вот только канонический способ не использует приведение указателей, а дублирует требующие наследования методы:


                          struct Bar {
                              super: Foo,
                          }
                          
                          impl Bar {
                              fn baz(&self) { self.super.baz() }
                          }

                          Получается несколько многословно, но рано или поздно эту проблему решат.


                          1. snuk182
                            27.06.2019 15:36

                            При наличии крупного функционала родителя эта многословность мгновенно встает огромной проблемой. Есть RFC на эту тему, но с ним проблем больше, чем без него.


                            1. mayorovp
                              27.06.2019 15:43

                              Это какой-то не тот RFC. Правильное решение тут — реализация чего-то вроде derive для произвольных трейтов.


                              Пока же можно какой-нибудь Into вместо наследования использовать.


                              1. snuk182
                                27.06.2019 16:35

                                Derive уже есть очень давно, но это точечное решение, которое надо руками подгонять под каждый отдельный типаж. Красиво такая штука реализована в Go — вложенные структуры без имен переносят сигнатуры своих публичных методов на внешнюю структуру. Этакий декоратор на стероидах. Rust такое наверное не светит — очень уж неявно.


                                Заменить наследование для задач именно наследования, а не подстановки — нечем. Существующие решения подразумевают копипаст, что не лезет ни в какие ворота. Можно бы исхитриться и реализовывать базовый типаж для реализаций типажа-наследника, чтоб не копипастить, но увы, orphan rules прилетают и бьют по попе. Да и специализация до ума не доведена.


                  1. Ryppka
                    27.06.2019 14:50

                    А как без нее решать низкоуровневые задачи? Вот прекрасная статья на тему: www.cs.kent.ac.uk/people/staff/srk21/research/papers/kell17some-preprint.pdf


        1. abondarev Автор
          25.06.2019 19:32

          Ох, вы открываете гигантский топик

          ну что же, тема то действительно интересная :)

          Rust как и C++ не имеет стабильного ABI, так что использование foreign interface (aka C-FFI) отличное решение.

          скорее всего единственно возможное. Поскольку нужно предоставить возможность использовать существующее ПО. Пока вижу что индустрия так устроена, что все хотят использовать свои наработки. Вон в банках до сих пор еще всякие VAX архитектуры и майнфреймы s/360 используют, плюс язык COBOL.

          да я как раз про unsafe, и согласен что уменьшение проблемных мест это хорошо.

          На счет ОС общего назначения, ну можно начать с ОС специального назначения, мы например хотим какой то модуль или драйвер написать. Но вот с драйверами как раз и показательная ситуация, сейчас определяющим является поддержка аппаратуры. В свое время мы даже хотели сделать совместимость с драйверами linux (но решили что частичной совместимости достаточно) и добавили других фишек, типа использование bsp от производителя. это я к тому, что без использования драйверов написанных на Си, вряд ли получиться что то используемое. А если не используемое, то опять канет в лету.

          А вот почему Rust'овое управление памятью чертовски безопасное (более безопасное, чем даже в языках с garbage collector'ом), быстро не описать.

          Вот прямо очень был бы благодарен, если пусть не быстро, а в отдельной статье, но Вы описали «почему». Сами занимаемся управлением памяти в проекте, и всякие тонкости очень интересны! :)


          1. mayorovp
            25.06.2019 23:26
            +1

            Вот прямо очень был бы благодарен, если пусть не быстро, а в отдельной статье, но Вы описали «почему». Сами занимаемся управлением памяти в проекте, и всякие тонкости очень интересны! :)

            Могу объяснить в двух словах.


            Во-первых, Rust следит за ссылками на объекты, как статически (по умолчанию), так и динамически (примитив RefCell), а потому всегда знает, эксклюзивно вы владеете объектом, или же к нему имеет доступ кто-то еще. И от этого знания зависит какие операции над объектом можно делать.


            Во-вторых, в Rust переменная уничтожается после переноса, что вместе с прошлым пунктом исключает класс ошибок use after free. Причем исключает статически.


            Сравните:


            // Си
            struct Foo *foo;
            // ...
            bar(foo);
            baz(foo->x); // упс, а foo уже нет - и мы это поймем только по ошибке памяти (если нам повезет)

            // C++
            std::unique_ptr<Foo> foo;
            // ...
            bar(std::move(foo));
            baz(foo->x); // упс, исключение

            // Rust
            let foo: Box<Foo>;
            // ...
            bar(foo);
            baz(foo.x); // ошибка компиляции


            1. abondarev Автор
              26.06.2019 12:04

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


              1. mayorovp
                26.06.2019 12:15
                +1

                Этот анализ никогда не выходит за пределы одной функции. Система типов Rust позволяет выразить утверждение, что переменная foo проживет, по крайней мере, столько же сколько и переменная bar. И если такого отношения между "внёй" и переменной нет — то ссылку на переменную передавать "во вню" нельзя.


                1. abondarev Автор
                  26.06.2019 12:22

                  Понятно, спасибо!


              1. DSolodukhin
                26.06.2019 12:17
                +1

                У каждой ссылки в Rust есть lifetime, т.е. время жизни. Компилятор проверяет, что время жизни ссылки не превышает время жизни переменной, на которую она ссылается. Вот очень простой пример кода, который в Rust не скомпилируется:

                fn get_ref_wrong<'a>() -> &'a i32 {
                    let s = 1;
                    
                    return &s;
                }
                

                Мы пытаемся вернуть ссылку на переменную, которая будет уничтожена при выходе из функции. Это ошибка.
                Вообще тема с ссылками и временами жизни одна из самых трудных для новичков в Rust, потому что в других распространенных языках такого нет и не получается сразу привыкнуть.


                1. abondarev Автор
                  26.06.2019 12:24

                  Ну этот пример конечно понятен, но блин, если кто то выделил переменную на стеке а возвращает указатель, то ну не знаю как его назвать, но точно не системным программистом.

                  За пример спасибо!


                  1. DSolodukhin
                    26.06.2019 12:39

                    Ну это очень простой пример, исключительно показать концепцию.
                    Но эта концепция работает везде, например, если вы хотите сохранить в структуре ссылку, то должны гарантировать, что ваша структура не будет существовать дольше, чем переменная, на которую вы взяли ссылку.
                    Так же ссылки по умолчанию иммутабельные, если вы хотите изменять данные по ссылке, вам понадобится явно это указать &mut data. Rust позволяет создать много иммутабельных ссылок и только одну мутабельную, если уже есть иммутабельная ссылка, то создать мутабельную нельзя — будет ошибка компиляции, и наоборот.

                    По расту есть хорошая книга, по крайней мере лучше чем официальный растбук — Блэнди Дж., Орендорф Дж. — Программирование на языке Rust. Там относительно неплохо объясняется работа со ссылками, концепции владения и заимствования.


                    1. abondarev Автор
                      26.06.2019 12:47

                      По сути, то за чем следит программист и приличные практики программирования, вынесены в синтаксис языка?
                      То есть конечно должны быть соглашения о том кто выделяет кто освобождает и кто может модифицировать данные по ссылке. Они всегда есть, если нет то проект быстро развалится!


                      1. Halt
                        26.06.2019 12:53
                        +1

                        По сути, то за чем следит программист и приличные практики программирования, вынесены в синтаксис языка?
                        Верно. Только не в синтаксис, а в семантику. В подавляющем большинстве случаев, в плане синтаксиса код не отличается от похожих языков. Существует такая штука как lifetime elision которая позволяет опускать тривиальные определения в тех случаях где все однозначно.


                        1. abondarev Автор
                          26.06.2019 13:10

                          В общем, нужно попробовать на чем нибудь небольшом, чтобы проникнуться идеями.


                          1. Halt
                            26.06.2019 13:17
                            +1

                            Разумеется. Наброшу вам еще немного полезных ссылок по теме:

                            1. Раздел основного сайта, посвященный embedded www.rust-lang.org/what/embedded
                            2. Книга по embedded разработке: rust-embedded.github.io/book
                            3. Большое собрание толковых ссылок по теме: github.com/rust-embedded/awesome-embedded-rust


                  1. Halt
                    26.06.2019 12:42

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

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

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

                    Таким образом ситуации вроде use after free, double free, инвалидации итератора или состояния гонок оказываются невозможными.


                    1. abondarev Автор
                      26.06.2019 12:53

                      В классических языках ответственность лежит на программисте. Rust это контролирует явно

                      Да. Написал об этом выше в комментарии


                  1. amarao
                    26.06.2019 12:43

                    Ситуация становится чуть-чуть сложнее, когда вы хотите передать указатель на переменную на стеке в соседний тред. В нормальном режиме в Rust это сделать нельзя (потому что не ясно сколько стек проживёт относительно треда), но библиотеках Rust'а есть такая конструкция, которая гарантирует компилятору, что треды закончатся до завершения текущей функции, так что можно безопасно передавать ссылки на свой стек в треды.


                    Вот эта штука, когда компилятор всё время озабочен тем, кто владеет, кто не владеет, кто когда завершается — это офигенно. Оно ловит огромное количество багов вокруг mutable/shared, а "обходные пути" вокруг ругани компиляторов обычно оказываются очень правильными архитектурными решениями.


                  1. PsyHaSTe
                    26.06.2019 18:42

                    Ну вот вам более реалистичный пример


                    #include <memory>
                    #include <iostream>
                    #include <functional>
                    
                    std::function<int(void)> f(std::shared_ptr<int> x) {
                        return [&]() { return *x; };
                    }
                    
                    int main() {
                        std::function<int(void)> y(nullptr);
                        {
                            std::shared_ptr<int> x(std::make_shared<int>(4));
                            y = f(x);
                        }
                        std::cout << y() << std::endl;
                    }

                    Тут та же история, но она уже припрятана под кучкой shared_ptr, которые правда не помогают.


                    Если же его наивно перенести на раст


                    fn f<'a>(x: &'a i32) -> impl Fn() -> i32 + 'a {
                        move || *x
                    }
                    
                    fn main() {
                        let y;
                        {
                            let x = 5;
                            y = f(&x);
                            println!("{}", y());
                        }
                        println!("{}", y());
                    }

                    То получите ошибку


                    error[E0597]: `x` does not live long enough
                      --> src/main.rs:9:15
                       |
                    9  |         y = f(&x);
                       |               ^^ borrowed value does not live long enough
                    10 |         println!("{}", y());
                    11 |     }
                       |     - `x` dropped here while still borrowed
                    12 |     println!("{}", y());
                       |                    - borrow later used here

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


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


                    1. mayorovp
                      26.06.2019 19:59

                      Примеры тут не совсем эквивалентны, в плюсовом коде ошибка не в main, а в функции f.


                      1. PsyHaSTe
                        26.06.2019 20:18

                        Я не переписывал 1в1, потому что это невозможно, а пытался догадаться, что хотел программист этим кодом сделать. Я предположил, что он хотел воспользовать x по ссылке в лямбде, что и изобразил в расте.


                    1. hhba
                      26.06.2019 22:45
                      +1

                      Пытаюсь понять, какой вариант выглядит более вырвиглазно — плюсовый или растовый…


                      1. PsyHaSTe
                        26.06.2019 22:47

                        А что вырвиглазного в растовом примере? Единственный генерик-параметр? Если очень неприятно, можно воспользоваться анонимным лайфтаймом


                        fn f(x: &i32) -> impl Fn() -> i32 + '_ {
                            move || *x
                        }


                        1. hhba
                          27.06.2019 08:49

                          Поскольку я с этим языком не знаком в достаточной мере, то отчасти моя реакция вызвана банальным непониманием написанного. Но мне кажется также, что синтаксис у языка объективно вырвиглазный. Как и у шаблонизированного кода на плюсах с использованием стандартной библиотеки. Хотя с Растом все даже хуже. Не зная ничего о шаблонах С++, можно тем не менее по наитию понять, что же там написано. Глядя же на первый вариант растового кода (с генериком) я вообще не понимаю «что хотел сказать автор». Да, еще раз, дело в незнании языка, но кажется, что это положение дел весьма показательно.


                          1. PsyHaSTe
                            27.06.2019 12:21

                            Нет, просто тут написано тупо больше, чем обычно пишут. Если вы видите кода в 2 раза больше, то и читать его в целом в 2 раза труднее.


                            Давайте разберем:


                            // объявляем функцию
                            fn 
                            // с единственным генерик-параметром 'a. Лаймтаймы обозначаются таким образом, достаточно быстро привыкаешь
                            f<'a>
                            // принимаем референс на i32, который живет не меньше чем 'a
                            (x: &'a i32) 
                            // возвращаем тип, реализующий трейт `Fn() -> i32` и живущий не меньше чем 'a.
                            -> impl Fn() -> i32 + 'a {
                                move || *x
                            }

                            Иными словами, мы говорим "я хочу вернуть лямбду, которой можно пользоваться все время, пока жива переменная x". Какие вещи тут непонятны. impl? Это просто экзистенциальный тип. В C#/Java за этим обычно скрывается просто бокс с интерфейсом, в хрусте компилятор подставит конкретный тип. Поэтому в расте можно вернуть какую-нибудь анонимную структуру, а в том же C# анонимный класс вернуть не получится, потому что его тип записать нельзя.


                            Да, еще раз, дело в незнании языка, но кажется, что это положение дел весьма показательно.

                            Не знаю, как по мне все достаточно просто. Причем я не плюсовик ни разу, посмотрите мои статьи, я C# разраб. И мне все это достаточно очевидно. Скажите, что конкретно в этой записи вас смущает, я просто серьезно не могу понять, что тут сложного, не считая б0льшего объема информации.


                            Просто если попробуете все то же записать при помощи той же джавы, у вас кода будете еще больше. Ну то есть как-то типа


                            @DeriveOutputType(@FunctionalInterface(int))
                            @BindLifetimeName(a)
                            FuncInt f(
                               @BindLifetimeName(a)
                               Reference<int> x
                            ) {
                               return MoveVariableOwnership(FuncInt(x))
                            }

                            стало ли понятнее?


                            1. hhba
                              27.06.2019 12:43

                              Во-первых спасибо за объяснения!

                              Скажите, что конкретно в этой записи вас смущает


                              Проблема в том, что смущает буквально все. Что-то конкретное трудно назвать.

                              я просто серьезно не могу понять, что тут сложного, не считая б0льшего объема информации


                              Вот в этом «не считая» кроется основная проблема — информации много, но понимания она не добавляет.

                              Просто если попробуете все то же записать при помощи той же джавы, у вас кода будете еще больше


                              И очень хорошо — кода больше, и он внезапно понятнее! То есть в Джаве введена разумная избыточность. И хотя я не понимаю, что в этом коде собственно происходит, но его синтаксис хотя бы понятен.


                              1. PsyHaSTe
                                27.06.2019 12:55
                                +1

                                И очень хорошо — кода больше, и он внезапно понятнее!

                                Тогда это просто вопрос привычки. Ну примерно как после паскаля с begin/end перейти на Си.


                                Могу посоветовать смотреть на разные языки. Обычно классика считается один си-подобный императивный, один логический, один функциональный, ну и sql. Нужно понимать, что привычный синтаксис не значит удобный. И соовтетственно


                                То есть в Джаве введена разумная избыточность.

                                Нет, просто вы привыкли её видеть.


                                И хотя я не понимаю, что в этом коде собственно происходит, но его синтаксис хотя бы понятен.

                                Выпишите просто что вас смущает. Ведь у каждого дизайн решения языка есть своя причина. Например, эрик липперт в статье про "топ 10 фич сишарпа о которых мы жалеем" в один из топа списка поставил "зря мы взяли из сишки то, что тип пишется впереди имени функции и переменных".


                                1. hhba
                                  27.06.2019 13:33

                                  Тогда это просто вопрос привычки. Ну примерно как после паскаля с begin/end перейти на Си.
                                  Могу посоветовать смотреть на разные языки. Обычно классика считается один си-подобный императивный, один логический, один функциональный, ну и sql. Нужно понимать, что привычный синтаксис не значит удобный. И соовтетственно


                                  Да ну нет же! То есть конечно фактор привычки нельзя игнорировать, но он не ключевой.

                                  Насчет Паскаля — перейдя с него на Си я очень порадовался, что вместо begin/end появились брекеты. Их конечно тоже надо уметь готовить, но они гораздо понятнее. И вообще я очень быстро «отошел» от паскалевских заморочек, именно потому, что Си понятнее.

                                  Насчет «Си-подобных императивных». Во-первых, кое-кто говорит, что Раст как раз из таких — и чем же они похожи с Си? Во-вторых, кое-кто говорит, что С++ из таких — но при использовании некоторых приемов программирования плюсовый код превращается в кашу что-то совершенно не похожее на Си. То есть этот термин (Си-подобность) какой-то неоднозначный. А если мы редуцируем вашу фразу до «императивный» (без указания референса), то ведь это не о синтаксисе получается…

                                  Насчет SQL — отличный пример, я написал в свое время немало запросов. И мне нравится лаконичность и внятность этого языка. Я сразу начал понимать, что и как там делается, без длительных объяснений. То есть внезапно беда не в императивном клинче моего мозга.

                                  Нет, просто вы привыкли её видеть


                                  Да конечно, я на Джаве писал сто лет назад, и это была другая Джава.

                                  Например, эрик липперт в статье про «топ 10 фич сишарпа о которых мы жалеем» в один из топа списка поставил «зря мы взяли из сишки то, что тип пишется впереди имени функции и переменных»


                                  Угу, часто об этом говорят, хотя разумных аргументов лично я не слышал. Слышал только разные инсинуации.

                                  Выпишите просто что вас смущает.


                                  Проще сказать, что я смог понять сам (если игнорировать ваши разъяснения). А именно — имею догадку, что «i32» как-то соотносится с int32_t, но это не точно. Еще есть смутное подозрение, что "&" имеет отношение к взятию адреса (то есть это ссылка на что-то, возможно это ref/out), но и это не точно. Вот и все.


                                  1. PsyHaSTe
                                    27.06.2019 14:23

                                    Насчет SQL — отличный пример, я написал в свое время немало запросов. И мне нравится лаконичность и внятность этого языка. Я сразу начал понимать, что и как там делается, без длительных объяснений. То есть внезапно беда не в императивном клинче моего мозга.

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


                                    Угу, часто об этом говорят, хотя разумных аргументов лично я не слышал. Слышал только разные инсинуации.

                                    Ну вот вам аргументы, почитайте.


                                    Проще сказать, что я смог понять сам (если игнорировать ваши разъяснения). А именно — имею догадку, что «i32» как-то соотносится с int32_t, но это не точно. Еще есть смутное подозрение, что "&" имеет отношение к взятию адреса (то есть это ссылка на что-то, возможно это ref/out), но и это не точно. Вот и все.

                                    Ну все так и есть. Возьмем еще раз


                                    fn f(x: &i32) -> impl Fn() -> i32 + '_ {

                                    Объявляем функцию f с параметром x типа ссылка на 32битное знаковое целое, которая возвращает тип, реализующий интерфейс () -> i32, то есть лямбду, возвращающую целое 32битное знаковое целое, и имеющее время жизни такое же, как входной аргумент.


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


                                    1. hhba
                                      27.06.2019 19:59

                                      Просто язык достаточно бедный


                                      Само собой, но вы ведь сами привели его в пример.

                                      Возьмите какой-нибудь другой бедный язык, будет ли он так же понятен?

                                      Объявляем функцию f с параметром x типа ссылка на 32битное знаковое целое, которая возвращает тип, реализующий интерфейс () -> i32, то есть лямбду, возвращающую целое 32битное знаковое целое, и имеющее время жизни такое же, как входной аргумент.


                                      Наверное сложность понимания обусловлена также и сложностью примера. Потому что из текстового описания у меня например формируется вопрос «а зачем это нужно?» )))


                                  1. BlessMaster
                                    27.06.2019 20:25
                                    +2

                                    На самом деле здесь больше информации с вполне конкретной целью: мы сообщаем компилятору, "что мы на самом деле имеем в виду". Впоследствии компилятор забирает у разработчиков массу головной боли и ручной работы, проверяя за них "всё ли согласованно написано в программе".


                                    На примере в несколько строчек эта полезность не так заметна и выглядит несколько странно. В крупном же и важном проекте, над которым работает немаленькая команда — можно только молиться на компилятор, который избавляет тебя от сегфолтов и прочих очень неприятных недоразумений, которые можно часами ловить в отладчике, или вообще до часа X не догадываться об их существовании.


                                    Потому что, когда такой час X "пробивает", обычно остаётся только устраивать сеанс спиритизма в три часа ночи, чтобы понять, ГДЕ этот чёртов косяк, из-за которого всё внезапно начало падать или почему остатки на счетах превратились в тыкву, и как это побыстрее исправить, ибо бизнес несёт убытки.


                                    Это, конечно, не серебряная пуля и не избавляет от всех багов вообще, но за то, от чего избавляет — это не такая уж и высокая цена писать всё чуть более многословно. Тем более, разработчики языка постарались насколько это возможно многословность нивелировать синтаксическим сахаром.


                                    Я бы даже добавил, что когда получается слишком раздутый код — в Rust это примета того, что "что-то пошло не так" и используется не лучшее архитектурное решение. Это особенно актуально для новичков, которые пытаются натягивать на Rust привычный стиль написания программ из других языков.


                                    1. hhba
                                      27.06.2019 22:56

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


                                  1. vvmtutby
                                    28.06.2019 22:08

                                    Насчет Паскаля — перейдя с него на Си я очень порадовался, что вместо begin/end появились брекеты
                                    А переходя с Clarion (1986)-- огорчились бы:
                                    If x = 5
                                      y = z * 3
                                    .


                                    В Modula-2 (1979), ADA ( стандарт и первый сертифицированный компилятор — 1983) и Oberon «детская болезнь» Алгола-60 решена на уровне синтаксиса языка.

                                    В экосистеме Си — внесли в Misra C указание для носителей «естественного интеллекта».


                              1. snuk182
                                27.06.2019 13:06
                                +1

                                То есть в Джаве введена разумная избыточность.

                                Популярность Котлина доказывает обратное.


                                1. hhba
                                  27.06.2019 13:07

                                  Не могу ничего сказать про Котлин, да и про Джаву мало что знаю (изучал в институте сто лет назад), так что я комментировал конкретный пример, и только.


              1. KanuTaH
                26.06.2019 12:22
                +1

                В Rust все сделано банально "вовне" ссылку передать нельзя :) Period.


                1. abondarev Автор
                  26.06.2019 12:25

                  То есть, для системных нужд его без unsafe не получится использовать?


                  1. KanuTaH
                    26.06.2019 12:34

                    Ну на низком уровне, где идёт работа с ресурсами (выделение, уничтожение) — скорее всего, да.


                  1. Halt
                    26.06.2019 12:47

                    Я не знаю что имел в виду KanuTaH коворя о «вовне», но unsafe совершенно ортогонален всему этому. Основная идея — разделение кода на безопасные и потенциально-опасные части. Если интерфейс модулей спроектирован верно, и инварианты контролируются, то все должно быть нормально.

                    В системных задачах, как правило, без unsafe не обойтись, но это не значит, что весь код будет им обмазан с ног до головы.

                    Например, в операционной системе Redox, написаной на Rust, unsafe встерчается только в строго ограниченных местах, тогда как бизнес логика, будь то менеджер страниц или диспетчер многозадачности, описывается на безопасном подмножестве.


          1. Halt
            26.06.2019 11:48
            +1

            Вот прямо очень был бы благодарен, если пусть не быстро, а в отдельной статье, но Вы описали «почему».
            Могу посоветовать классический уже пост одного из отцов основателей на эту тему: Fearless Concurrency.

            Ну и выше уже писали, что unsafe не отключает проверки, он разрешает дополнительные потенциально опасные операции (и это важно). Что именно происходит хорошо описано тут: You can’t “turn off the borrow checker” in Rust.


            1. abondarev Автор
              26.06.2019 11:51

              спасибо!


              1. Halt
                26.06.2019 11:53
                +2

                Всегда пожалуйста. Если что, с вопросами можете обращаться в личку.

                P.S.: Про разработку embedded категорически рекомендую блог человека, стоящего на острие прогресса Rust в этой области. По сути он и есть прогресс: blog.japaric.io

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


                1. abondarev Автор
                  26.06.2019 12:05
                  +1

                  Хорошо, спасибо. Если что обратимся :)
                  Блог прикольный!


        1. mayorovp
          25.06.2019 23:08

          но под общую гребёнку попадают и потенциально полезные (конкурентное изменение общего состояния)

          Но ведь в Rust есть все нужные примитивы для этой цели...


    1. mayorovp
      25.06.2019 23:02

      умеет быть совместимым в обе стороны с С-ABI.

      Вообще-то С++ так тоже умеет, extern "C" вроде же как раз для этого сделан...


    1. kovserg
      26.06.2019 01:00
      -2

      Рещил как-то попробывать rust — впечатление смешанные.
      1. скачать инсталятор для windows — квест
      2. скачал инсталятор для 32bit windows запустил и он бодро установил 64bit rust вместо 32bit
      3. обнаружил в директории .cargo/bin файлы идентичны по 5.7Мб которые по сути являются ссылками. ( 67мб просто 12 ссылок )
      4. побывал специально на слабой машине — rust очень тормозной в сравнении с другими тормознее только cuda-вский компилятор.

      Весь такой системный язык так невнимательно относится к системе.
      Выглядело так что сейчас этого синкансена придётся тащить на буксире.


      1. mayorovp
        26.06.2019 08:52

        обнаружил в директории .cargo/bin файлы идентичны по 5.7Мб которые по сути являются ссылками. ( 67мб просто 12 ссылок )

        Так это же и правда ссылки: на диске файл хранится всего в одном экземпляре, просто у него есть 12 разных имен.


        1. mayorovp
          26.06.2019 17:32

          Для тех кто не верит


      1. amarao
        26.06.2019 12:37

        Ну, формально, вам надо просто поставить WSL, а там-то с Rust всё просто супер. Включая кросс-компиляцию под винды.


      1. Ryppka
        26.06.2019 13:37

        rustup Вам в помощь, и ставьте все, для чего компоновщик есть. Хотя на Windows вроде требуется полный компилятор: или msvc, или mingw32-w64 (он и 32-битный бывает).


        1. TargetSan
          26.06.2019 14:25

          Ставим Visual Studio Build Tools и имеем всё недостающее. На страничке rustup это вроде было описано.


      1. snuk182
        26.06.2019 17:21
        +1

        Чем-то вы страшным занимаетесь, будто вам Рабинович напел Карузо.
        Под винду скачивается единственный экзешник, который даже не требует админских прав. Запускается, далее, далее, готово. Для пользователей без опционально требуемой Visual Studio 2017 (для сишных биндов, если будете использовать) можно вместо одного из Далее указать "хочу gnu вместо msvc", поставится сразу легкая версия mingw. В итоге все компактно сложено в ~/.cargo и ~/.rustup, запускается отовсюду, использует все ядра и потоки по умолчанию (может быть потому и тормоза на слабой машине).


  1. ripandtear
    25.06.2019 17:54

    Занимаюсь программированием различного Embedded'a на протяжении ~7 лет, скромное мнение:

    — Для решения проблем с надежностью есть стандарт MISRA C. Может быть есть и другие, но с ними я не знаком.
    — Очень много legacy и того что мы используем каждый день, написано на С. Да все и так я думаю в курсе. Я работал и работаю со многими закрытыми и открытыми DSP-процессорами и ядрами, практически везде используется С89 или С99 для написания к ним прикладных программ. Все кастомные тулчейны и т.п. — это все для С.
    — Я бы рад перейти например на тот же Rust. Но на него не переходят в своих тулчейнах Analog Devices, Qualcomm, CEVA, и др. компании. Т.е. как уже было выше отмечено, в первую очередь поддержка должна идти от них.
    — Продакшен конечно разный бывает, но лично у нас смотреть в сторону Rust'a начнут, когда появятся нормальные рабочие инструменты от тех же производителей железа, с которыми мы работаем.


    1. abondarev Автор
      25.06.2019 17:59

      но лично у нас смотреть в сторону Rust'a начнут, когда появятся нормальные рабочие инструменты от тех же производителей железа, с которыми мы работаем

      Все правильно, это однин из главных сдерживающих факторов.
      Разработка собстенных средств разработки (как например предлагали на конференции компилятор языка Си для ARM) естественно будет содержать ошибки. И вот как с этим быть непонятно, но когда индустрия дозреет, и будет несколько отлаженных и доступных компиляторов, вот тогда…


      1. Halt
        26.06.2019 12:32

        Маловероятен, но в принципе возможен и обратный вариант. Например если, условно, www.tockos.org или Embox станут популярными настолько, что вендоры будут видеть в их поддержке конкурентное преимущество и уже сами озаботятся совместимостью тулчейна.

        С учетом гарантий, которые дает Rust, мне не кажется это таким уж невероятным, тем более, что существует инициатива по сертификации Rust для критических систем.


  1. oam2oam
    25.06.2019 18:01

    Если говорить о надежности программ и скорости разработки, то почему не рассматривается язык Ада? Он к тому же и позиционировался как язык для встроенных систем. Ну и «выстрелить себе в ногу» на нем о-очень сложно…
    К тому же на нем отлично пишется для микроконтроллеров. Ну и нет абсолютно никакого зоопарка со стандартами и компиляторами. К слову сказать, gcc поддерживает не так много языков, но среди них — Ада.
    А так, кажется порой, что абсолютно все возможности современных языков сначала (очень давно) были в Аде, а потом уже в пошли в массы. К тому же, очень-очень мало языков поддерживают параллельное выполнение на уровне самого языка (не библиотек или там классов), а это сейчас все более актуально.
    Да что говорить — все же программирование когда-то, похоже, свернуло не туда и не стали популярны Ада, Пролог…


    1. abondarev Автор
      25.06.2019 18:10

      Язык Ада безусловно обсуждался в рамках данной дискуссии и в рамках обсуждения языка Оберон. Кстати, в кулуарах Дмитрий Дагаев на вопрос об Ада сказал, что не хочет использовать его на АЭС (а использовал Оберон) поскольку сейчас существует только один сертифицированный компилятор для подобных систем и как Вы понимаете он не у нас разрабатывается и его просто не продают.
      Еще возникает вопрос с кросс-платформенностью, но это по идее должен решать gcc.


      1. Siemargl
        26.06.2019 19:55

        Как будто существует сертифицированный компилятор Оберона…

        Там вообще содомия творится — стандартного компилятора нет, а есть миллион самодельных компиляторов и у каждого _свои_ расширения (потому что куцый функционал стандарта — даже без базовых библиотек), и неоднозначности толкования.

        Ада — это цельный продукт, но она не сильно то проще С++ %-) И ее реализации вполне могут быть неполными — без менеджера памяти, например.


        1. vvmtutby
          28.06.2019 19:41
          +1

          О) компилятор Оберона … Там (такое) творится
          Если мы возьмём Active Oberon ( см. «доклад про Оберон технологии» ) «за основу», то всё будет выглядеть, как правило, «диаметрально противоположно». Другие языки семейства — не менее полезны и «результативны».

          A) Т.к. несколько причастен к «постам и вопросам», приведу сокращённый ответ ( хотя бы, как повод к поиску первоисточника):

          Язык Ада безусловно обсуждался в рамках данной дискуссии и в рамках обсуждения языка Оберон.… на вопрос об Ада…


          Дмитрий Дагаев, «отвечая на посты и вопросы»:

          1. В части функциональной безопасности (...)
          (...) есть компилятор Ады GNAT, но только один ( остальные … ): GNU Ada New York Translator.
          Поэтому использовать его даже для категорий B и C мы не можем. Росатом (...) покупает по конкурсу у трех независимых поставщиков. А тут один (...)
          Более того, даже для категорий B и С продукт должен создаваться в рамках аналогичного жизненного цикла со всеми нашими требованиями к документированию, верификации, валидации и пр.
          (...)
          2. В части категории A, Ада не соответствует требованиям по причине избыточности.


          1. Siemargl
            28.06.2019 22:37

            Active Oberon выглядит неплохо, но компилятор единственный под свою частную песочницу. Существенных проблем (кроме того что рантайм песочницы WinAOS/LinAOS имеет качество некоммерческого студенческого проекта) там отсутствие проверок переполнения/качества вычислений и контроль ошибок только кодами возврата. Принципиальной выгоды перед промышленным стандартом IEC 61131-3 ST я не вижу никакой, скорее наоборот.

            Говорить, что исключаем опенсорсный! компилятор АДЫ из рассмотрения по вышеуказанной причине, имея для АО еще худшую ситуацию — это прямой и явный зашквар (заинтересованное участие в «тендере» выбора решений).


            1. abondarev Автор
              29.06.2019 13:41

              позволю привести немного переписки от уже упомянутого Дмитрия Дагаева:

              по поводу АДЫ

              Маленькая ремарка в комментариях про Аду: есть одна компания AdaCore и один GNAT — Gnu Ada NewYork Translator. А Росатом даже ластик покупает у 3 независимых поставщиков. А вот остальные разработчики компиляторов Ады связаны с организациями типа Минобороны США. У нас на дне Оберона С.И.Рыбин делал очень интересный доклад https://forum.oberoncore.ru/viewtopic.php?f=155&t=6380&p=107709#p107353 .

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

              По поводу компиляторов и рантаймов:
              Ну и компиляторы размером 3000-50000 строк.

              Время компиляции Оберонов меньше сишных компиляторов в тысячи раз! И есть наша советская школа, например XDS (Алексея Недоря) — оптимизирующий компилятор со скоростью, близкой к компилятору Турбо-Паскаля!
              Количество ошибок компиляторов Оберона очень маленькое, поскольку они простые. Да, бэкенды нужно отлаживать, но программа из 10тыс строк может быть «интеллектуально управляемой», а из 10 млн — нет.
              Для высоких уровней оптимизации есть общая проблема корректности после оптимизации.

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

              Лично я придерживаюсь мнения, что это работает, но только до определенного момента. Когда технология начинает реально использоваться, причем независимыми разработчиками в разных (не единичных проектах), этот подход перестает работать. И тогда одним из вариантов является опять же opensource.

              Скоро выпущу пре-версию Мульти-Оберона, объединив 3 бэкенда: натив X86, трансляцию в С и LLVM.

              LLVM (да и С тоже) как раз в сторону открытого подхода


  1. Fenzales
    25.06.2019 18:12
    +1

    Тео де Раадт из OpenBSD в своё время разразился хорошим письмом на эту тему:

    I wasn't implying. I was stating a fact. There has been no attempt
    to move the smallest parts of the ecosystem, to provide replacements
    for base POSIX utilities.
    > Note that with Cgrep and haskell-ls, there do in fact exist
    > implementations/analogues of two of the mentioned utilities in a
    > memory safe language (Haskell).

    Are they POSIX compliant? No. They are completely different programs
    that have borrowed the names.

    By the way, this is how long it takes to compile our grep:

    0m00.62s real 0m00.63s user 0m00.53s system

    Does Cgrep compile in less than 10 minutes?
    tl;dr Rust (или любой другой язык) не вытеснил C, потому что никто не пишет на Rust сопоставимые альтернативы.


    1. abondarev Автор
      25.06.2019 18:20

      Для некоторых вещей скорость компиляции не так критична. Хотя конечно это важно для массового испольнования.

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


      1. Fenzales
        25.06.2019 22:03

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


    1. Revertis
      25.06.2019 19:54

      Кажется, замену grep'у уже пишут.


      1. snuk182
        26.06.2019 15:17

        Не просто кажется, но уже давно есть и даже дистрибьютится.


        1. Revertis
          26.06.2019 15:56

          А, ну вот. Круто ведь!


        1. Halt
          26.06.2019 16:56

          Я бы добавил еще что он давно уже используется по умолчанию для поиска по проектам в VSCode.


      1. Fenzales
        26.06.2019 17:16

        В *BSD не линуксовый GNU/grep используется, по-моему.


  1. zloe_morkoffko
    25.06.2019 18:26

    Идея заключается в том, чтобы экспортировать (декларировать) интерфейс и объекты могут подключаться именно через этот интерфейс.
    В IDE для WxWorks можно прямо мышкой включать\выключать\настраивать компоненты системы. Соответствующие модули и их зависимости тоже описаны на каком-то языке разметки(сейчас не вспомню уже)


    1. abondarev Автор
      25.06.2019 18:40

      Ну включать выключать настраивать модули, дело не хитрое, в linux ядре можно спокойно вызвать менюшку написанную на qt, и там прекрасно пощелкать мышкой. Тут все гораздо серьезнее. если я правильно понял то это близко к filter graph.
      А WxWorks 653 имеет описание в xml формате, и там действительно много чего можно настраивать. Но даже у нас в Embox, наверное больше возможностей по конфигурации системы.


  1. MSC6502
    25.06.2019 21:12
    +1

    Вся история IT-индустрии показывает, что по какому-то иррациональному, никому не ведомому признаку программистское сообщество выбирает самый сложный, самый опасный, самый трудный и рандомнобихевористческий инструмент для своих разработок. Примеров есть некоторое количество (С++, js, java, python ). Самое печальное, что эти инструменты занимают лидирующие позиции в рейтинге ЯП. Детально знать и держать в голове тысячу страниц описания с++ не может ни один человек в мире. А уж знать и предвидеть результаты интерференционных явлений, возникающих при использовании десятков разных библиотек, наверное под силу одному-двум суперпрограммистам из близлежащих галактик. В то же время тщательно разработанные инструменты объявляются немеэйнстримными, устаревшими, несовременными и проч. Это поведение коллективного разума IT сообщества невозможно понять. Появляются десятки новых языков уровня КП 3 курса с комьюнити в пару тысяч человек. Это как если бы на заводе инженер в целях самовыражения решил бы в новой машине использовать новые болты с резьбой М13.726 или 4.735. Думаю, что на следующий же день он искал бы новое место работы. Информационные технологии занимают в жизни планеты всё большее место. Результаты использования небезопасных инструментов и технологий мы все знаем. Это постоянно обнаруживаемые уязвимости разного уровня опасности в ОС, приводящие у утечкам конфиденциальных данных, потерям финансовых средств. Методология разработки программного обеспечения, равно как и языков программирования, должны уже давно стать глобальными, наднациональными задачами. Пора уже отбросить узкокорпоративные шоры и погоню за кратковременной выгодой. Основа основ мировой IT структуры — операционные системы и средства разработки должны быть общедоступны и бесплатны. Причем эти основы должны быть сконструированы хоты бы с такой степенью тщательности, как Ада. Да, уже конкретные прикладные пакеты могут быть платными. Но некоторая тщательно проработанная общедоступная база должны быть. Потому что, чем дальше, тем больше появляется несовместимых стандартов и решений, в итоге на решение проблем совместимости уходят громадные ресурсы, которые могли бы быть использованы более продуктивно. (Если что, я сторонник паскале-подобных языков — Ада, Delphi, Оберон, Seed7).


    1. abondarev Автор
      26.06.2019 10:22

      Основа основ мировой IT структуры — операционные системы и средства разработки должны быть общедоступны и бесплатны.

      Ну так opensource есть, Linux gcc gdb?
      Причем эти основы должны быть сконструированы хоты бы с такой степенью тщательности, как Ада.

      Ну есть другой подход делать надежные программы, «Собор и базар»

      (Если что, я сторонник паскале-подобных языков — Ада, Delphi, Оберон, Seed7)

      Дело вкуса, я уж точно не противник этих языков.
      Можно долго холиварить по поводу какой язык лучше. Но мне кажется, что время покажет для каких задач подходит тот или иной язык. Наприме, java задумывался как язык для всех типов платформ, кросплатформенный. В итоге основное серверная часть была как раз на нем написана, наверное для этих целей он был наиболее хорош, но это же не маленькие устройства, хотя попытки постоянно были. ой забыл про Android, но например Kotlin, замечательно зашел в этом плане как замена Java. Или python, сейчас на нем делают очень много прототипов и проводят моделирование, язык лучше отвечает характеристикам для подобных задач. Есть старые языки, которые почему то ушли в прошлое, есть языки которые так и не нашли свою нишу.

      В общем, я стороник opensource, а языки нужны разные для разных целей. А если Вы сторонник Оберона почему бы не присоединиться к проекту по обучению этому языку Информатика 21


    1. taujavarob
      27.06.2019 17:53
      -1

      Вся история IT-индустрии показывает, что по какому-то иррациональному, никому не ведомому признаку программистское сообщество выбирает самый сложный, самый опасный, самый трудный и рандомнобихевористческий инструмент для своих разработок.
      Две теории, почему так:

      Во-первых, «фишеровское убегание». Это вот что: самка выбирает привлекательного самца, чтобы ее дети-самцы тоже были привлекательными. При этом признак «любви к привлекательным самцам» у самки оказывается полезным — ее дочки-самки тоже унаследуют страсть к бесполезным, но прекрасным мужским чертам, в результате чего обеспечат своим сыновьям репродуктивный успех. Со временем эта система идет вразнос (почему и называется «убеганием»), то есть два признака — павлиний хвост самца и любовь к павлиньему хвосту у самки — развиваются до тех пор, пока признак мужской красоты не станет почти летальным. При этом процесс может начаться с небольшого случайного отклонения женских предпочтений, а потом наступает цепная реакция.

      Вторая теория — «гандикапы» Амоца Захави. Она вот о чем: самки выбирают самцов с вредным признаком, потому что выживание таких самцов свидетельствует об их высокой приспособленности. Гены этой приспособленности унаследуют не только сыновья, но и дочери, то есть в совокупности такой выбор окажется полезен.


      Вспоминая Докинза (С)


  1. johnfound
    25.06.2019 23:51
    +2

    Все выше пишут как будто производительность все еще удваивается каждые 18 месяцев.


  1. KanuTaH
    26.06.2019 00:13
    +1

    М-да, ещё когда я в институте учился, лет 20 назад, ломались копья на тему «C vs Ada/Oberon». Типа вот-вот, ещё чуть-чуть… Прошло 20 лет, а дискуссии все те же :) Ну моднявый Rust ещё появился, да. Но насчет него тоже автор статьи выше совершенно справедливо написал про «5 лет назад» :) Modern language — это, конечно, хорошо, и даже замечательно, но продакшн есть продакшн.


    1. abondarev Автор
      26.06.2019 10:30

      Не только Rust появился. Появилось много языков. На Rust как раз до сих пор еще мало пишут. Но всякие Kotlin, Go нашли свою нишу и прекрасно применяются в продакшене.

      А обсуждение очень важно как раз для развития. Время само раставит все по своим местам. Пока C стандарт де факто по крайне мере для системного программирования, но может в будущем появится более лучшая альтернатива!


      1. KanuTaH
        26.06.2019 12:04
        +1

        Ну я конкретно про системное программирование имею в виду. Споры все те же, один в один (даже предлагаемые альтернативы все те же, за исключением Rust), ну и воз все там же :)


        1. abondarev Автор
          26.06.2019 12:12

          Тут согласен, Си для системного программирования пока никто не переплюнул, поэтому все и вкладываются в эту сферу и драйвера и операционки и обучение.


    1. hhba
      26.06.2019 17:34

      Один мой вузовский препод говорил следующее: «Я знал старого одного программиста, он недавно умер, так вот он часто говорил, что Си скоро умрет. Но пока это не произошло — открываем редактор и пишем...»


      1. perfect_genius
        26.06.2019 19:26
        +2

        Вывод: Си нас всех ещё переживёт.


  1. AVI-crak
    26.06.2019 00:49

    Дело в том что язык Си — очень близок с идеей предварительной компиляции. Ключевое слово — «предварительной». Проверка кода на безопасность должна быть произведена до окончательной сборки.
    То-есть нужно сначала хорошо подумать, для того чтобы ваша новая функция выполняла именно то что вы задумали, и ничего более. Проблема в большом количестве необходимых действий, примитивных по своей сути — но в них можно ошибиться. Это в языках более высокого уровня в функции может быть всего одна или две математические операции — а всё остальное пространство заполняет длиннющие имена переменных. В Си не так, имена короткие — а действий много.

    Ошибки которые можно допустить в таком коде — уже давно всем известны, и многие анализаторы кода их успешно находят. Проблема в том что эти анализаторы внешние. Нет такой IDE, что в режиме набора текста будет показывать ошибки, и главное — варианты их решения.
    Наверное это очень сложно — распознать массив, его границу, и возможный выход за границу массива. Настолько сложно — что в данный момент нет даже попыток создания подобного плагина.

    Я утверждаю, проблема безопасности Си — это полное отсутствие инструментов проверки/подсказки алгоритмов пользователя во время его набора. Когда появится поддержка — все вопросы отпадут сами собой.


    1. KanuTaH
      26.06.2019 00:59

      Даже если таких инструментов нет прямо в IDE, то это решается путем создания правильного процесса CI. Перед тем, как попасть в основную ветку, новый код должен быть в обязательном порядке и автоматически проверен всеми используемыми анализаторами и пройти все тесты. Без этого merge просто не должен проходить. А уж инструментов для решения подобных задач вагон и маленькая тележка. Но и все эти анализаторы не дают 100% гарантии отсутствия ошибок. Впрочем, расты с оберонами точно так же сами по себе таких гарантий не дают.


    1. staticmain
      26.06.2019 08:33
      +1

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

      Последний QtCreator на лету проводит clang анализ и прямо на проблемной строчке подсуазывакт, что не так.


      1. lamerok
        26.06.2019 12:11
        +1

        Clion вполне себе на ходу делает статический анализ кода…


      1. AVI-crak
        27.06.2019 14:32

        А ведь я проверял… QtCreator не различает в параметрах функции: числовые/символьные константы, горячие переменные, и перемененные с произвольной разрядностью. Видеть их видит, а связать поведение алгоритма с их типом не может.

        Самое простое — функция принимает адрес статического массива, и адрес элемента массива для изменения/чтения.
        Адрес элемента числовая/символьная константа — даже gcc видит ошибку в случае промаха, QtCreator не пытается выполнять проверку.
        Адрес элемента внешняя переменная — gcc ругается, QtCreator молчит.
        Адрес элемента число с произвольной разрядностью — gcc бодро занимается ускорением, иногда чего-то там пишет в отладку, QtCreator прикидывается шлангом.


    1. abondarev Автор
      26.06.2019 10:49

      Это в языках более высокого уровня в функции может быть всего одна или две математические операции — а всё остальное пространство заполняет длиннющие имена переменных. В Си не так, имена короткие — а действий много.

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

      Я утверждаю, проблема безопасности Си — это полное отсутствие инструментов проверки/подсказки алгоритмов пользователя во время его набора.

      Ну как уже ответили, такие механизмы есть, по крайней мере проблемы решаемые путем: применения разных компиляторов, применение статических и динамических анализаторов, CI, тестирования. Все это прилично работает для небольших программ. Другое дело, что если программа большая например ядро Linux, проанализировать все возможные утечки памяти становиться не реально. И да я ядре делают собственные инструменты анализа, которые помогают улучшать надежность программ, но это как раз не от хорошей жизни.

      Вероятно проблема Си в том, что изначально речь шла о профессиональных программистах, которые хорошо знают алгоритмы, организацию ЭВМ, структуры данных и следовательно пишут программы высокого качества. То есть это был переход от ассемблера к чему то более поддерживаемому. Поэтому данный язык хорошо «прижился» в системном программировании. Подразумевается, разработчик должен осознавать, что он делает.


    1. PsyHaSTe
      26.06.2019 19:04

      Проблема безопасности в Си — что для него фундаментально невозможно написать анализатор который поймает достаточно количество багов, чтобы считать язык безопасным. Ну физически, если у вас сложение двух числе это УБ то вам никакой анализатор не поможет. Потому что если у вас 90% ложноположительных срабатываний, то по сути инструмента и нет. Не помню, где читал, но для нормальной работы инструмент должен давать меньше 5% ложноположительных срабатываний.


      Язык вроде раста именно это и делает. Он запрещает вещи, которые трудно анализировать, чтобы иметь возможность это делать. Запретили иметь больше одной изменяемой ссылки — найс, можно написать на это анализатор. В си две мутабельных ссылки валидная история, и написать на это проверку не получится. А из этой проверки идет много следствий, которые в си хотелось бы иметь, но нельзя, потому что фундамента нет.


      В этом плане Джон Кармак очень хорошо высказался в своем твиттере


      Coincidentally, I just started writing some rust… I find this sentiment strange; people don’t look to other languages because you can’t do something in c++, but more often because you can.


  1. AVI-crak
    26.06.2019 01:49

    Перед тем, как попасть в основную ветку

    Я о том и говорю — автоматический анализ должен быть в самой IDE. Чтобы встроенная!!! (а кстати почему они все внешние?) система контроля версий не допускала сохранения заведомо ошибочного кода.
    То-есть проблема не в языке, а в программном обеспечении для работы с ним.


    1. abondarev Автор
      26.06.2019 10:53

      Я о том и говорю — автоматический анализ должен быть в самой IDE.

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


    1. PsyHaSTe
      26.06.2019 19:05

      Осталось только научиться определять заведомо ошибочный код с достаточной точностью, чтобы программист не отключил эту проверку. Я не вижу как для Си это решается. Там наоборот, вся философия что программист "знает что делает".


      1. Labunsky
        26.06.2019 19:21

        А в чем проблема-то? Мы же не говорим, что русский плохой, потому что в нем можно построить грамматически корректные фразы, которые при этом не несут смысла, "не работают". И уж тем более не бежим создавать новый просто из-за того, что люди страдают с выражением своих мыслей на существующем


        1. PsyHaSTe
          26.06.2019 19:26

          Если бы мы писали программы на русском, то это был бы плохой язык, да.


          От него не требуется даже той толики строгости, которая требуется для ЯП.


          1. Labunsky
            26.06.2019 19:40

            Но почему? Если человек на естественном (очень гибком и прощающем) языке пишет с ошибками, то мы его ругаем, зовем неграмотным. Если же программист пишет на очень строгом языке с ошибками, о многих из которых его предупреждают любые современные редактор и компилятор, — мы ругаем язык?.. И ведь ему за это часто платят, в отличие от двоечника Пети


            1. PsyHaSTe
              26.06.2019 20:16

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


              И да, мы не решаем проблему "кто виноват", язык или программист, вопрос в том, что делать с этим. Есть факт, что люди ошибаются. Просто факт. Мы либо можем сказать "ну окей" и ловить баги в приложении, либо попытаться что-то с этим сделать. Вопросы "зачем ты написал код с багом" я считаю неконструктивными.


              1. Labunsky
                26.06.2019 20:37
                +1

                например, у пилотов гражданской авиации

                Это отличный пример, кстати, недавно как раз видел расследование аварии на взлетной полосе из-за одного пропущенного уточнения. Правда, софт для аналогичных задач все равно на языках с возможностью прострела ноги пишется


                что делать с этим

                В моем представлении, надо в первую очередь поднимать квалификацию, и свою, и чужую. А то так все просто разленятся и через 20 лет будут жаловаться на слишком свободный раст)


                1. KanuTaH
                  26.06.2019 20:57

                  +1. Люди застраховали свой зад от какого-то определённого класса ошибок в каких-то определённых случаях (по крайней мере, они так считают), и носятся с этим, как будто это решит все проблемы разработки ПО. Это не говоря уж о том, что everything comes for a price (причем даже не только и не столько в виде какого-то рантайм оверхеда, сколько в необходимости изобретать какие-то обходные пути там, где ранее все "просто работало" — с умеренным приложением головы, разумеется).


                  1. PsyHaSTe
                    26.06.2019 22:44
                    +1

                    Programming Defeatism: No technique will remove all bugs, so let's go with what worked in the 70s.


                    1. KanuTaH
                      26.06.2019 22:54

                      Nope, я скорее про "закон дырявых абстракций" и "бесплатного сыра не бывает" :) Если бы "наворачиванием абстракции на абстракцию" можно было решать любые проблемы — ядра ОС и прошивки для железа уже писали бы на яве с шарпом. Там такое любят :)


                      1. PsyHaSTe
                        26.06.2019 23:01

                        Nope, я скорее про "закон дырявых абстракций" и "бесплатного сыра не бывает" :)

                        платность тут состоит в том, чтобы уметь этими инструментами пользоваться. Но как по мне, выучить единожды инструмент чтобы применять его N раз всегда имеет смысл. Программирование в этом и заключается, к слову. Но люди хотят автоматизировать все, кроме собственного быта. Некоторые.


                        Если бы "наворачиванием абстракции на абстракцию" можно было решать любые проблемы — ядра ОС и прошивки для железа уже писали бы на яве с шарпом. Там такое любят :)

                        Андроид на яве и написан. Singularity — на шарпах. Что до винды и линухов, тут то что называется "исторически сложилось". Нет никаких причин почему именно си, просто так вышло. Потому что популярно было в 70е. в нулевых популярной была жаба, андроид написали на ней. Сейчас раст достаточно популярен, фукси (новая ос от гугла вместо андроида) емнип на нем пишется.


                        Так что прогресс идет.


                        1. KanuTaH
                          26.06.2019 23:07

                          Ядро Android написано на C/C++, никакой явой там и не пахнет. Ява там только как рантайм для приложений (и то не для всех — Android NDK никто не отменял).


                          1. PsyHaSTe
                            26.06.2019 23:16

                            Я не считал точно, но жава-строк в андроиде явно больше, чем код ядра. Вся std библиотека и все остальное — это джава.


                            1. KanuTaH
                              26.06.2019 23:21

                              Да, основной рантайм для пользовательских приложений там — это Java-классы (но не только, есть ещё и NDK). Но не ядро.


                1. PsyHaSTe
                  26.06.2019 22:36

                  В моем представлении, надо в первую очередь поднимать квалификацию, и свою, и чужую. А то так все просто разленятся и через 20 лет будут жаловаться на слишком свободный раст)

                  Ну то есть "пишите код без багов". Так не бывает.


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


                  Напомню, что человек не может держать в памяти больше 7 объектов одновременно, и это не зависит от квалификации.


                  В моем представлении, надо в первую очередь поднимать квалификацию, и свою, и чужую. А то так все просто разленятся и через 20 лет будут жаловаться на слишком свободный раст)

                  Ну и отлично. Что расстраиваться-то?


                  1. Labunsky
                    26.06.2019 23:32

                    Так не бывает

                    Ну понятное дело, но и смена языка тоже не спасет)
                    Про помнить каждую переменную и количество объектов не понял, опять же, в чем именно си хуже любого другого языка. К слову, в нем нет NULL'ов, зато есть самые обычные нули


                    Что расстраиваться-то?

                    Как чего, падению квалификации. Софт-то кому-то писать надо, нам же его и использовать, если доживем


                    1. PsyHaSTe
                      26.06.2019 23:51

                      Ну понятное дело, но и смена языка тоже не спасет)

                      Вполне. От некоторого класса проблем. Чем серьезнее язык, тем больший этот класс.


                      Про помнить каждую переменную и количество объектов не понял, опять же, в чем именно си хуже любого другого языка. К слову, в нем нет NULL'ов, зато есть самые обычные нули

                      Ну вот я не могу без подсказки от системы типов что это Option<T> помнить, что тут нулл выскочить может.


                      Как чего, падению квалификации. Софт-то кому-то писать надо, нам же его и использовать, если доживем

                      Ну а это типичное "раньше было лучше".


                      1. KanuTaH
                        27.06.2019 00:05

                        Ну а это типичное «раньше было лучше».

                        Ну, смотря в чем «лучше». Типичный Java/C# (а тем более JS) разработчик сейчас, как правило, не имеет понятия ни о том, как работать с памятью, ни о приемах оптимизации кода в плане правильного использования кешей, ни о том, как внутри себя устроены какие-нибудь мутексы, и к чему приводит их использование в плане производительности. Да что там говорить, он даже не особо интересуется, к чему «внутри» приводят его попытки конкатенации строк «в лоб», через оператор "+". Не царское то дело. Как только нужно будет написать что-то действительно оптимальное, такой разработчик тут же сдуется, упрется в порог инструментария. Он просто не будет знать, что можно как-то по-другому. С другой стороны, человек, имеющий опыт относительно низкоуровневого программирования, как правило, все же задается вопросом «а что там под капотом», поэтому он даже на всех этих «абстракциях» пишет лучше, чем граждане, пишущие исключительно на «удобных» языках, а главное — он всегда имеет выбор.

                        P.S. Вот выше johnfound написал «все выше пишут как будто производительность все еще удваивается каждые 18 месяцев», его сначала даже заминусовали, я помню, а я вот сразу понял, о чем он. У меня те же ощущения.


                        1. PsyHaSTe
                          27.06.2019 00:37

                          Ну, смотря в чем «лучше». Типичный Java/C# (а тем более JS) разработчик сейчас, как правило, не имеет понятия ни о том, как работать с памятью, ни о приемах оптимизации кода в плане правильного использования кешей, ни о том, как внутри себя устроены какие-нибудь мутексы, и к чему приводит их использование в плане производительности.

                          Да-да, а типичный C++ разработчик не знает о поколениях ГЦ, как работает хотсвап джиттер и прочее. Что из этого следует?


                          Да что там говорить, он даже не особо интересуется, к чему «внутри» приводят его попытки конкатенации строк «в лоб», через оператор "+".

                          Да, только потом оказывается, что они в курсе, как это работает, и конкатенация через плюс оказывается быстрее, чем попытки плюсовиков ускоирть жс через стрингбилдеры какие-нибудь. Уже проверяли тут же, на хабре.




                          Советую не тешить в себе ложный элитизм.


                          1. KanuTaH
                            27.06.2019 00:44

                            Да-да, а типичный C++ разработчик не знает о поколениях ГЦ, как работает хотсвап джиттер и прочее. Что из этого следует?

                            Почему же? Если он начал писать на managed-языках, он узнает. Может быть, даже напишет свой. У него даже вполне может быть для этого необходимый background.

                            Да, только потом оказывается, что они в курсе, как это работает, и конкатенация через плюс оказывается быстрее, чем попытки плюсовиков ускоирть жс через стрингбилдеры какие-нибудь. Уже проверяли тут же, на хабре.

                            Не в курсе про жс, но в Java компилятор таки пытается заменять такие «лобовые» конкатенации на работу через StringBuffer:

                            docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.18.1

                            Но он может и не справиться с такой оптимизацией в один прекрасный момент. А гражданин, который «в курсе как это работает, и конкатенация через плюс быстрее» будет чесать репу — как же так, раньше же быстро работало, а тут вдруг тормоза не пойми откуда. Всегда работало, а тут вдруг перестало.

                            Советую не тешить в себе ложный элитизм.

                            :) Я учту :)


                            1. PsyHaSTe
                              27.06.2019 01:29

                              Почему же? Если он начал писать на managed-языках, он узнает. Может быть, даже напишет свой. У него даже вполне может быть для этого необходимый background.

                              Ну вот если у жсера начнутся проблемы с памятью, он точно так же узнает про её устройство и сможет оптимизировать.


                              Не в курсе про жс, но в Java компилятор таки пытается заменять такие «лобовые» конкатенации на работу через StringBuffer:

                              Такова жизнь манагед-разработчиков, что кроме процессора у него еще есть ВМ, и он должен знать поведение джита и рантайма в таких-то условиях. Тоже некий уровень сложности, который нужно учитывать.


                              :) Я учту :)

                              Правда, очень рад. Нечасто такое слышу.


                              1. KanuTaH
                                27.06.2019 01:33

                                Такова жизнь манагед-разработчиков, что кроме процессора у него еще есть ВМ, и он должен знать поведение джита и рантайма в таких-то условиях. Тоже некий уровень сложности, который нужно учитывать.

                                На самом деле у меня лично просто есть забавная история как раз про случай, когда оптимизатор JIT'а с этим не справился. Меня просто попросили переписать некий кусок на плюсах, потому что «плюсы же быстрее». Переделав в этом куске конкатенации в цикле в цикле в цикле на StringBuilder (там не требовалась синхронизация), я ускорил кусок в разы for no charge, и продолжил лентяйничать дальше. Это я не с потолка взял пример, это моя личная боль :)))


                                1. PsyHaSTe
                                  27.06.2019 01:34

                                  Да я понимаю, в шарпах та же проблема. Но жс как раз на этот случай имеет эвристику (точнее v8). Проверяли на разных версиях, результат стабильный. за жабу говорить не буду, скорее всего там такого нет.


                          1. Labunsky
                            27.06.2019 00:59

                            а типичный C++ разработчик не знает о поколениях ГЦ

                            На самом деле, раньше сборку мусора писали как раз для C/C++


                      1. Labunsky
                        27.06.2019 01:31

                        Вполне. От некоторого класса проблем. Чем серьезнее язык, тем больший этот класс.

                        Это защита из серии мягких углов. Да, маленького ребенка нельзя одного оставлять в помещении, нужны и заграждения, и надзор, и разъяснения, что в рот брать надо, а что нет. Но чем он становится старше, тем больше свободы мы ему даем: сначала доверем ему ПВА для апликации на уроке труда, позже паяльник, а потом и вовсе сварку. Потому что с опытом тот начинает понимать, что и как ему делать, используя полученные знания с большей эффективностью. Даже если неаккуратное использование и опасно для здоровья


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


                        1. PsyHaSTe
                          27.06.2019 01:33

                          Только лучше эту опасную сварку применять точечно, огораживая ~unsafe~ знаком ОСТОРОЖНО: СВАРКА.


                          И если что-то пошло не так, сразу понятно, куда глядеть.


            1. anatolymik
              26.06.2019 20:30
              +1

              Но почему? Если человек на естественном (очень гибком и прощающем) языке пишет с ошибками, то мы его ругаем, зовем неграмотным.
              Не бывает плохих разработчиков, бывает плохой язык. Странно что ракеты летают, а атомные станции — работают. :)

              Ежели серьезно, на мой взгляд, дело в человеке, а не в инструменте. Правда это другая крайность. Безусловно удобные и эффективные инструменты должны быть.


              1. Labunsky
                26.06.2019 20:44

                на мой взгляд, дело в человеке, а не в инструменте

                Это и моя же позиция)


                удобные и эффективные инструменты должны быть

                Вот только почему нынешние неудобные? То есть, тот же раст на самом деле имеет кучу интересных фич, но зачем-то позиционируется многими как замена си со смущающей меня аргументацией. Так тяжело существовать параллельно, что ли?)


                1. anatolymik
                  26.06.2019 21:31

                  То есть, тот же раст на самом деле имеет кучу интересных фич, но зачем-то позиционируется многими как замена си со смущающей меня аргументацией.
                  А те кто позиционируют — ничего другого не знают. Вы на скольких языках пишете? Я по роду деятельности: ассемблер, СИ, C++, C#, Java, Phyton (web и 1С перечислять не буду, давно в прошлом). Уверен и у вас не один. Ибо данное вами высказывание наталкивает меня именно на такие мысли.

                  Так тяжело существовать параллельно, что ли?)
                  Безусловно да. Ибо человек, который знает только один язык, ограничен в восприятии контекста решаемых задач. А значит все должно быть как у него :) «Когда в руках только молоток, все начинает казаться гвоздем».

                  Вот только почему нынешние неудобные?
                  Я не могу сказать что они так уж в основе не удобны. У каждого из, есть как плюсы так и минусы. Поэтому я за совмещение подходов, а не за то чтобы подвести все под одну черту. В любой подобласти нашей сферы, есть своя специфика. Ну и это безусловно подводит нас к тому, что и инструменты будут разными и с разными возможностями. Мы ведь не запускаем самолеты с ракетной площадки. Мы контекст задачи учитываем.

                  Так же и тут. Я и не против того чтобы все унифицировать. Но наша индустрия еще не выработала всего нужного. Есть legacy, есть лишнее, а что-то отсутствует. За много лет её существования поменялся ряд задач, которые мы решаем. Многие из них перестали вписываться в ту картину которая сложилась. Нужно переосмысление всего. И как следствие выработка новых подходов, механизмов и аппаратуры. А людей, которые решат данную задачу, просто нет. Потому что и спроса на них нет. А ведь это исследовательская работа, которая требует очень длительного вовлечения по времени. Ситуация осложнена тем, что корпорации деньги зарабатывают. И развитие как таковое отсутствует. Рынок насытился, и все думают о том чтобы прибыль осталась на том же уровне.

                  Я в прошлом, стремился к тому же самому. Все упростить. В результате пока решал эту задачу, разобрался много в чем. И надобность унифицировать отпала. Нет ничего сложного чтобы совмещать подходы. Сложно придумать это совмещение. А стремление было вызвано тем, что когда я что-то новое узнавал, мне казалось что я теперь все знаю и хотел всем жизнь облегчить. А по факту испортил самому себе. Время только потерял. Но не все так уж и печально. Лучшее что я вынес из этой практики, так это то, что такая унификации сейчас, ведет к переусложнению, избыточности и излишней нагрузки на вычислительные системы.

                  Поэтому, люди которые однозначно стремятся все унифицировать, мне видятся либо не опытными специалистами, либо специалистами которые не дают никакой оценке проделанной работе, либо они просто пластинка. На работе таких много, постоянно с ними борешься. В результате, придут, своими решениями все сделают хуже. После чего они получают пинка под зад, а после идут в другое место портить там. А далее, начальство на их место садит таких же, если не хуже. Ну, зато не скучно. Не работать же :) Категорично вроде, но не лишено смысла. Сам таким был :)


                1. PsyHaSTe
                  26.06.2019 22:43
                  +1

                  Вот только почему нынешние неудобные?

                  Неудобство понятие относительное. Например, ассемблер неудобнее Си, а си неудобнее раста. Через 20 лет будет язык удобнее их всех. И еще через 20. Развитие в том и заключается, что палки-копалки и камни превращаются в экскаваторы и отбойные молотки. Заметьте, мы не заставляем людей научиться выкапывать по 20 тонн земли в час, мы меняем инструменты. Даже если взять лучших копателей за всю историю и заставить учить людей как это делается вы не сможете достичь результатов техники. Потому что люди это люди. Они ошибаются, они часто теряют внимание, да и в целом рассеяные. Ожидать от них полной самоотдачи и внимательности 24/7 немного наивно. Лучше дать инструмент, который скажет "чел, ты переменную используешь, я такой не вижу. Может ты ошибся"? или "А тут у тебя ошибка может возникнуть, а ты никак не обрабатываешЬ", или "Вот ты версию библиотеки обновил, а вместо Т у тебя тут Option<T> начал приходить, обработай, дорогой".


                  1. Labunsky
                    27.06.2019 00:53

                    Например, ассемблер неудобнее Си, а си неудобнее раста

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


                    Лучше дать инструмент, который ...

                    Этот инструмент зовется "анализатор". Статический подвид входит в практически любой современный компилятор, иногда даже отдельным модулем. Благодаря этому, последним можно выставить обработку предупреждений анализатора как ошибок компиляции, чтобы "почти как в расте". Все уже придумано за нас)


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


                    Но на самом деле, 2/3 примеров не пройдут даже лексический анализ


                    1. PsyHaSTe
                      27.06.2019 01:32
                      +1

                      На первый вопрос проще всего взять уже известное мерило


                      Все языки одинаково мощные, если рассматривать их с точки зрения эквивалентности машине Тьюринга, но это не та мощь, которая важна программисту. (Никто ведь не хотел бы программировать машину Тьюринга). Мощь языка, в которой заинтересован программист, возможно, трудно определить формальными методами, однако одно из объяснений этого понятия заключается в свойствах, которые в менее мощном языке можно получить, только написав на нем интерпретатор для более мощного языка. Если в языке A есть оператор для удаления пробелов из строк, а в языке B его нет, это не делает A более мощным, чем B, так как в B можно написать процедуру, которая делала бы это.

                      Но, скажем, если язык A поддерживает рекурсию, а B — нет, это нечто, что нельзя исправить написанием библиотечных функций.

                      Насчет второго раст это и есть плюсы с прикрученным анализатором, в котором язык чуть-чуть подправили чтобы анализатор был точнее. Если посмотреть раст образца 2008 года, то это что-то среднее между плюсами и сегодняшним растом. Причем с тех пор по сути поменялся только синтаксис на более мл-подобный, но судить язык по синтаксису это такое.


                      Так не все делают по простой причине — часто нет времени вылизывать все дочиста, если код может работать и так.

                      Ну вот я считаю, что в программе не должно быть CVE с памятью вообще. Даже если код "ну типа работает". Это не те проблемы, на которые можно забить в приложении, если только это не прототип.


                      1. Labunsky
                        27.06.2019 02:27

                        Никто ведь не хотел бы программировать машину Тьюринга

                        Мы этим уже занимаемся. Наши физические компьютеры — ее модели, мы просто используем синтаксическую прослойку, которую разворачивают компиляторы, интерпретаторы и виртуальные машины


                        огораживая ~unsafe~ знаком ОСТОРОЖНО: СВАРКА

                        Эти знаки точно так же ставятся в любом другом языке. Всегда заранее известно, какие операции могут привести к какому результату, ЯП полностью детерменирован


                        Ну вот я считаю, что в программе не должно быть CVE с памятью вообще

                        На два стула сесть не выйдет. Если писать полностью без unsafe, то можно легко натолкнуться на повышенный расход памяти (эти умные указатели любят позависать). Глобально надо смотреть в сторону сборщиков мусора, позволяющих совмещать подходы. И тех же самых, что и для C/C++, динамических анализаторов типа valgrind


                        1. mayorovp
                          27.06.2019 07:04

                          Со сборщиками мусора та же фигня: да, простой оторваный цикл они соберут. А вот как бы удаленный объект, забывший отписаться от событий — уже нет...


                          1. Labunsky
                            27.06.2019 13:29

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


                            1. Ryppka
                              27.06.2019 13:38

                              Свободу сборщикам мусора!)
                              Если честно, не совсем понял, что имеется в виду: при каких-то настройках gc собирает не только освободившуюся память или дурно влияет на корректно работающий код?


                              1. Labunsky
                                27.06.2019 14:04

                                Имел ввиду, что gc может ждать, пока память станет свободной по его мнению, а может получить явный вызов по освобождению объекта "здесь и сейчас"


                                Дурно он влияет на производительность: большое число объектов отслеживать и обрабатывать сложно. Поэтому программист может ему помогать, делая такие вызовы на части объектов заранее


                                1. mayorovp
                                  27.06.2019 14:31

                                  "На часть объектов" программист не может сделать вызов GC по определению мусора: если у программиста есть способ указать на объект, то он точно мусором не является.


                                  1. Labunsky
                                    27.06.2019 14:41

                                    Почему нет?


                                    int* temp = gc_calloc(BIG_SIZE, sizeof(int));
                                    for (...) {
                                    // работаем с temp'ом
                                    }
                                    
                                    // начиная с этого момента массив больше не используется, является мусором в памяти
                                    // сразу освобождаем, чтобы не насиловать сборщик
                                    gc_free(temp);


                                    1. mayorovp
                                      27.06.2019 14:47

                                      Как это работает? И что будет, если я сделаю вот так?


                                      int* temp = gc_calloc(BIG_SIZE, sizeof(int));
                                      
                                      global_var = temp + 1;
                                      
                                      gc_free(temp);

                                      А если без вызова gc_free?


                                      1. Labunsky
                                        27.06.2019 14:57

                                        что будет, если я сделаю вот так?

                                        Зависит от реализации, конечно, но обычно: в глобальной переменной будет храниться адрес на освобожденный участок в памяти, а обращение к ней — UB


                                        Если без вызова — то будет висеть, так как завязан на глобальную переменную, куда ему деться


                                        1. mayorovp
                                          27.06.2019 15:28

                                          в глобальной переменной будет храниться адрес на освобожденный участок в памяти

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


                                          Если без вызова — то будет висеть, так как завязан на глобальную переменную, куда ему деться

                                          А как он поймет, что есть такая переменная и там находится именно указатель?


                                          1. Labunsky
                                            27.06.2019 15:45

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

                                            Если мы где-то забудем освободить память, но и в глобальную переменную не запихнем, он ее отследит и освободит без волнений. Помимо прочего, обычно они защищают нас от double free, проверяя, есть ли освобождаемый объект в использовании. Нужно брать лучшее от обоих миров)


                                            А как он поймет, что есть такая переменная и там находится именно указатель?

                                            Ну как сборщик мусора ищет сами указатели и их обрабатывает — это можно очень долго и много писать)


                                            В общем случае, сканируются регистры, стэк и статичные регионы типа data (как раз случай глобальной переменной). Для каждого найденного указателя f просто проверяется, есть ли в базе объектов (обычно это простая таблица) такая пара (p, size), что p <= f < p + size. Если есть — объект, описываемый парой, в использовании, то есть не мусор


                          1. vvmtutby
                            28.06.2019 21:42

                            … простой оторваный цикл они ( сборщики мусора) соберут. А вот как бы удаленный объект, забывший отписаться от событий — уже нет...
                            GC прав: «объект, который забыли отписать от событий» — его удалять просто небезопасно…


                            1. mayorovp
                              28.06.2019 22:13

                              Прав конечно же. Но утечка ресурсов от этого не исчезает.


                        1. TargetSan
                          27.06.2019 11:31

                          Эти знаки точно так же ставятся в любом другом языке. Всегда заранее известно, какие операции могут привести к какому результату, ЯП полностью детерменирован

                          Увы, нет. И С/С++ с их просто огромным количеством UB/ID тому вполне себе подтверждение. Вы не можете в С сказать "нулевые указатели у меня будут только здесь, в других местах их не пропускать". Так что программа на С/С++ будет представлять из себя здание с огромным ОСТОРОЖНО СВАРКА во весь фасад.


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


                          1. Labunsky
                            27.06.2019 13:30

                            Появление UB — это детерменированное поведение. Мы всегда знаем, где он есть, а где его нет, это четко прописано в спецификации. Просто не знаем заранее, какой из возможных результатов скомпилируется. Недетерменированные автоматы же на x86 никак не загнать


                            1. Halt
                              27.06.2019 13:37

                              В таком случае UB sanitizer был бы тривиальным. Проблема в том, что определены только условия наступления UB, но не то, есть ли он в данном конкретном примере кода или нет. В общем же случае, сюда еще набрасывает проблема останова.

                              Поэтому единственно достоверный сопособ исключить UB — предотвратить его статически, на уровне системы типов.


                              1. Labunsky
                                27.06.2019 13:55

                                UB sanitizer был бы тривиальным

                                Большое его подмножество и. Сложно найти неинициализированную переменную? Да ну нет. Знаковое переполнение? Да тоже просто. Нал поинтер? Куда проще


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


                                единственно достоверный сопособ исключить UB — предотвратить его статически, на уровне системы типов

                                Пока не вышло


                                1. PsyHaSTe
                                  27.06.2019 14:32
                                  +1

                                  Уб специально завозят для того, чтобы не писать анализатор, которые его ловит, потому что это сложно. Каким образом кто-то другой напишет анализатор, если разрабы языка сдались в этом вопросе?


                                1. 0xd34df00d
                                  27.06.2019 17:02

                                  Большое его подмножество и. Сложно найти неинициализированную переменную? Да ну нет. Знаковое переполнение? Да тоже просто. Нал поинтер? Куда проще

                                  Особенно после того, как код был скомпилирован с оптимизациями, полагающимися на то, что UB в коде не бывает.


                                  1. Labunsky
                                    27.06.2019 18:34

                                    Такой поиск проводится до стадии оптимизаций


                                    1. 0xd34df00d
                                      27.06.2019 18:50

                                      UB может возникнуть после инлайнинга, например.


                                      Да и вообще,


                                      // tu1.cpp
                                      
                                      void bar(int*);
                                      
                                      void fooChecked(int *ptr)
                                      {
                                        if (ptr)
                                          bar(ptr);
                                      }
                                      
                                      // tu2.cpp
                                      
                                      void bar(int *ptr)
                                      {
                                        *ptr = 0;
                                      }
                                      
                                      // tu3.cpp
                                      
                                      int main()
                                      {
                                        fooChecked(nullptr);
                                        bar(nullptr);
                                      }

                                      В каком месте вы тут «очень просто» (то есть, как минимум, без cross-TU analysis) мы что-то про null скажем?


                                      1. Labunsky
                                        27.06.2019 19:30
                                        -1

                                        Нигде, потому что он явно передается программистом, исполнение и последующее падение будет полностью корректным запланированным поведением. Вот если он случайно появляется из вызова или операций...


                                        1. 0xd34df00d
                                          27.06.2019 19:46

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


                                          Будет вам легче, если я вместо nullptr там подставлю вызов функции, которая потенциально может вернуть nullptr?


                                          1. Labunsky
                                            27.06.2019 20:02
                                            -1

                                            Ну да, потому что тогда мне моя иде нарисует предупреждение о проверке на NULL. Такие ошибки легко ловятся простым фильтром: необходима проверка либо до доступа, либо после изменения. И кто мы-то, я один тут)


                        1. PsyHaSTe
                          27.06.2019 12:26

                          Мы этим уже занимаемся. Наши физические компьютеры — ее модели, мы просто используем синтаксическую прослойку, которую разворачивают компиляторы, интерпретаторы и виртуальные машины

                          Нет, вы этим не занимаетесь. Вы пишете на своих удобных ЯП а во что оно трансформиуется уже вопрос десятый. От того что хачкель компилируется в х86 ассемблер вы не теряете его мощи, гарантий и ленивости.


                          Эти знаки точно так же ставятся в любом другом языке. Всегда заранее известно, какие операции могут привести к какому результату, ЯП полностью детерменирован

                          Скажите, если у меня есть сегфолт в программе на Си, каким грепом мне найти все конкретные места, где теоретически он мог возникнуть?


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

                          С чего это? Ансейф не имеет отношения к повышенному расходу памяти.


                          (эти умные указатели любят позависать

                          Все считается в компайл тайм, какие зависания?


                          1. Labunsky
                            27.06.2019 13:45
                            -2

                            вопрос десятый

                            Только если для страуса в песочнице. Надо понимать, какой код переходит в какую последовательность инструкций, для этого даже есть удобное по. В идеале, надо уметь и на машину поста/тьюринга писать программы: необходимость писать даже регистры и операции над ними с нуля дает отличное понимание компьютерной архитектуры


                            Ансейф не имеет отношения к повышенному расходу памяти… Все считается в компайл тайм

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


                            какие зависания

                            Зависания как у не самой умной молодежи: соберутся в кучку с пивом, включают блютуз-колонку шумят, занимают место, отказываются уходить


                            1. PsyHaSTe
                              27.06.2019 14:37
                              +1

                              Только если для страуса в песочнице.

                              Для большинства софта. Потому что это называется абстракция.


                              Надо понимать, какой код переходит в какую последовательность инструкций, для этого даже есть удобное по. В идеале, надо уметь и на машину поста/тьюринга писать программы: необходимость писать даже регистры и операции над ними с нуля дает отличное понимание компьютерной архитектуры

                              Занимался этим на курсе матолгике в универе, давно. Смысла в практическом программировании у такого ноль ровно. Даже знания кэш локалити полезнее.


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

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


                              1. Labunsky
                                27.06.2019 14:53

                                Занимался этим на курсе матолгике в универе

                                Неужели вас заставляли курсе на втором выделять на ленте регистры и память, писать операции над ними, а потом применять их ко входных данным на ленте? Думаю, нет. В основном потому, что:


                                Смысла в практическом программировании у такого ноль ровно

                                Без "такого" не будет практического программирования, потому что нечем будет компилировать, не на чем исполнять)


                                1. PsyHaSTe
                                  27.06.2019 14:56
                                  +1

                                  Неужели вас заставляли курсе на втором выделять на ленте регистры и память, писать операции над ними, а потом применять их ко входных данным на ленте?

                                  В машине тьюринга нет никаких регитсров, там есть только бесконечная лента и алфавит. И да, мы этим занимались.


                                  Думаю, нет.

                                  Ох уж это гадание по интернету.


                                  Без "такого" не будет практического программирования, потому что нечем будет компилировать, не на чем исполнять)

                                  Знаю людей, которые никогда такого не делали, но им есть на чем компилировать. Как так?


                                  1. Labunsky
                                    27.06.2019 15:12
                                    -1

                                    В машине тьюринга нет никаких регитсров, там есть только бесконечная лента и алфавит

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


                                    Знаю людей, которые никогда такого не делали, но им есть на чем компилировать. Как так?

                                    Да, можно писать на джаве под спринг, собирать все градлом, под капот ни одной абстракции не залезать. И быть легко заменимым


                            1. 0xd34df00d
                              27.06.2019 17:06

                              Надо понимать, какой код переходит в какую последовательность инструкций,

                              С учётом ?Ops хоть?


                              для этого даже есть удобное по. В идеале, надо уметь и на машину поста/тьюринга писать программы: необходимость писать даже регистры и операции над ними с нуля дает отличное понимание компьютерной архитектуры

                              А программы в исчислении SKI уметь писать надо?


                              Ну, мне просто интересно, где ваше «надо» заканчивается.


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


                              1. Labunsky
                                27.06.2019 18:45

                                Ну, мне просто интересно, где ваше «надо» заканчивается

                                Нигде, процесс учебы не является чем-то конечным


                                И можно было одним постом написать все, а то я аж испугался количеству входящих на почте


                        1. 0xd34df00d
                          27.06.2019 16:59

                          Эти знаки точно так же ставятся в любом другом языке.

                          Только некоторые языки, увы, не требуют этого ставить.


                    1. 0xd34df00d
                      27.06.2019 16:58

                      Этот инструмент зовется "анализатор". Статический подвид входит в практически любой современный компилятор, иногда даже отдельным модулем. Благодаря этому, последним можно выставить обработку предупреждений анализатора как ошибок компиляции, чтобы "почти как в расте".

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


                      1. Labunsky
                        27.06.2019 18:53

                        На практике это пока никем не продемонстрировано. Синтаксис нас ограничивает уже сейчас, заявления есть, а супер-надежного ПО — нет, как и массовой миграции


                        1. 0xd34df00d
                          27.06.2019 18:54

                          То есть, все те люди, которые пишут на всяких Coq и Agda формально верифцицрованные вещи, ничего вам не демонстрируют?


                          Ну ок.


                          1. Labunsky
                            27.06.2019 19:25

                            Пишут много кто и много на чем. Это не значит, что ошибок меньше, а если меньше, то из-за языка


                            Но я рад, что вы тут все сбондились, мне за пару комментариев минусов уже прелетело больше, чем за последние 4 поста пришло. Комьюнити выходит дружное, но не мотивирующее


                            1. 0xd34df00d
                              27.06.2019 19:47

                              Пишут много кто и много на чем. Это не значит, что ошибок меньше, а если меньше, то из-за языка

                              Что-то мне подсказывает, что про всякие там коки, и как и что на них пишется, вы не особо слышали.


                              1. Labunsky
                                27.06.2019 20:06

                                Так точно, коки принимаю только в форме листьев по праздникам, как и любой другой не очень умный человек


                  1. Ryppka
                    27.06.2019 09:11
                    -1

                    Например, ассемблер неудобнее Си, а си неудобнее раста

                    Для многих низкоуровневых задач C удобнее Rust'а. Такие задачи обычно невелики, а синтаксического шума в C меньше, так что меньше и возможность описаться или еще как ошибиться. C создан для таких задач, а Rust делает их решение возможным.
                    Преимущества у Rust'а появляются при масштабировании задачи.


              1. PsyHaSTe
                26.06.2019 22:39

                Не бывает плохих разработчиков, бывает плохой язык. Странно что ракеты летают, а атомные станции — работают. :)

                Ну так если посмотреть на правила приемки самолетов, то там не си используется, а его подмножество удивительно похожее на какой-нибудь раст опять же. Только вместо системы типов и компилятора там ручная проверка и, возможно, тесты.


                Ежели серьезно, на мой взгляд, дело в человеке, а не в инструменте.

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


                1. anatolymik
                  27.06.2019 00:03

                  Ну так если посмотреть на правила приемки самолетов, то там не си используется, а его подмножество удивительно похожее на какой-нибудь раст опять же.
                  Это что-то доказывает? Это доказывает что везде надо применять этот язык? Самолетостроение все-таки несколько иная стезя. И подходы следовательно иные, сугубо специализированные.

                  Человека нельзя кардинально поменять. Нельзя сказать «с завтрашенго дня пиши без багов».
                  Речь по-моему не о багах. Кардинально можно уволить. А в утверждения типа «пишет плохо но круто идеи выдает» я давно не верю. Т.к. многократно видел что это не так. И т.к. если человек плохо разбирается в деталях, то и в глобальным смысле он видит еще меньше. Если человек не может кардинально меняться, ему надо менять профессию. Например на стройку пойти работать. Если конечно у него задача найти свою нишу. А если в целом, я не пойму откуда такая любовь к таким людям. Я с такими даже говорить не стану(в профессиональном смысле, профессионализм на человеческие качества никак не влияет). Что уже говорить о том, чтобы считаться с ними. Интересно выходит, делают хуже, а требуют к себе равного отношения. «Защита прав слабоумных».

                  Человеку можно дать более удобный инструмент, но и все.
                  Можно, и инструмент нужно улучшать. Но сути само по себе оно не меняет. Если человек на менее удобном инструменте не мог выполнять работу нормально, то он и на более удобном не сильно то себя проявит. Потому что основ не понимает. А бывает еще когда дурака грамота только портит. Скажем так, с удобством инструмента, должны расти и требования к задачам. А если так, то планка по задачам снижаться не будет, с чего бы ради он будет делать нормально, когда в голове больше двух переменных удержать не может? Но если планка не повышается, а инструмент удобнее и проще, и как следствие он ту или иную задачу уже может выполнить, то он, выходит обезьяна. Т.к. по сути по методичке уже делает, не понимая основ. И в том и в другом случае, мне видится, дело в человеке.


                  1. PsyHaSTe
                    27.06.2019 01:25

                    Это что-то доказывает? Это доказывает что везде надо применять этот язык? Самолетостроение все-таки несколько иная стезя. И подходы следовательно иные, сугубо специализированные.

                    Просто если есть бесплатные бенифиты, то почему бы ими не воспользоваться?


                    Речь по-моему не о багах. Кардинально можно уволить.

                    Нет, речь как раз о баге. Типичный пример, когда забыли проверить на нулл и разыменовали нулевой указатель. Или у вас такого не бывает?


                    Можно, и инструмент нужно улучшать. Но сути само по себе оно не меняет. Если человек на менее удобном инструменте не мог выполнять работу нормально, то он и на более удобном не сильно то себя проявит. Потому что основ не понимает.

                    Если человек не знает физику, то микробиологом ему не быть, потому что он основы не понимает.


                    Простите, но нет. Есть известный закон дырявых абстракций, который явно говорит, что достаточно знать +-1 уровень от своей текущей чтобы полноценно выполнять свою работу. Кругозор — это полезно, никто не спорит.


                    Но как уже сказано, знание "С++" никак не делает челвоека более хорошим разработчиком, чем знание C#.


                    1. anatolymik
                      27.06.2019 09:40

                      Просто если есть бесплатные бенифиты, то почему бы ими не воспользоваться?
                      Можно воспользоваться, кто спорит то. А что до этих бенефитов, они в самолетостроении не просто, а потому что там ошибка стоить дорого будет. И в таком ракурсе распространенные ошибки нужно исключать. Поэтому если говорить о подобного рода разработках, то да. Никакого Си там быть не должно. Там нужна строго специализированная аппаратура и языки под неё. Но мы по-моему не крутимся в этой сфере. Почему постоянно оно приводится как пример? Что-то обилия разработчиков из самолетостроения в комментариях не наблюдается. Похоже, это у нашего брата просто «бамбалейо».

                      В C# тоже бенефиты, например память освобождать не надо. А как следствие сбурщик мусора требует процессорное время. И память освобождается дольше. И если тоже самое делать на С++, то результат себя лучше покажет, когда речь о высокой нагрузке. Вы не будете с этим спорить?

                      Нет, речь как раз о баге. Типичный пример, когда забыли проверить на нулл и разыменовали нулевой указатель. Или у вас такого не бывает?
                      Бывает. Когда я драйвер пишу, у меня DriverVerfier включен постоянно. Когда приложение, то memoryleakdetector прикомпоновываю. Все возможные инструменты проверки у меня работают постоянно. И я отлаживаю то что пишу, даже если в функции две строчки. И прорабатываю под отладчиком все возможные пути работы той или иной функции. А потом в комплексе все смотрю. Это не сложно. Обычная проверка того, что делаешь. Но, те о ком вы говорите, так не заморачиваются. Потому как им просто лень. Возникает вопрос, а зачем такой пассажир нужен? Как вы ранее упомянули, людей не поменяешь. Я, понимая это, по возможности буду избегать с такими встречи. И не буду входить в положение их тонкой и ленивой натуры.

                      Если человек не знает физику, то микробиологом ему не быть, потому что он основы не понимает.
                      А смена языка равна смене профессии? Языки высокого уровня, по сути ускорили разработку. Языки с «бенефитами» не только ускорили, но и ограничили. Поэтому и область применения у них разная.

                      Я переформулирую свой тезис. Раз речь о багах, и тем более если речь о багах, сути оно, тем более не меняет. При разработке чего-либо(т.е. при решении той или иной задачи, я это так называю), вы вырабатываете решение, концептуальное. У одной и той же задачи решений может быть несколько, со своими как плюсами так и минусами. И нередко приходится совмещать разные решения в одно. Чтобы качества добиться. Так вот если человек в принципе концептуально не умеет решать задачи, язык ему не поможет. Ибо в логике решения задач у него проблемы. А null dereference и иже с ними здесь всего лишь детали. А человек который умеет решать задачи, управиться с такими проблемами.

                      Простите, но нет. Есть известный закон дырявых абстракций, который явно говорит, что достаточно знать +-1 уровень от своей текущей чтобы полноценно выполнять свою работу.
                      Скажите, а ассенизатор хорошо выполняет свою работу?

                      Кругозор — это полезно, никто не спорит.
                      Я говорил не о кругозоре, я говорил о профессионализме. Если вы умеете только что-то одно, вы не сможете решать более сложные задачи. Потому что не знаете ничего в смежных областях. А если и знаете то не факт что понимаете до конца, т.е. это уже опыт. А чтобы создать что-то реально новое, нужно знать очень много. Т.к. хорошие решения на самом деле, решаются не на одном уровне.

                      Но как уже сказано, знание «С++» никак не делает челвоека более хорошим разработчиком, чем знание C#.
                      Никак, согласен. Только, знание только С# тем более.


                      1. PsyHaSTe
                        27.06.2019 12:31

                        Почему постоянно оно приводится как пример? Что-то обилия разработчиков из самолетостроения в комментариях не наблюдается.

                        Окей, давайте не будем.


                        В C# тоже бенефиты, например память освобождать не надо. А как следствие сбурщик мусора требует процессорное время. И память освобождается дольше. И если тоже самое делать на С++, то результат себя лучше покажет, когда речь о высокой нагрузке. Вы не будете с этим спорить?

                        Вполне вероятен сценарий, где C# будет лучше за счет той же компактификации кучи, откуда кэш локалити и вот это все. Смотреть надо по ситуации.


                        Бывает. Когда я драйвер пишу, у меня DriverVerfier включен постоянно. Когда приложение, то memoryleakdetector прикомпоновываю. Все возможные инструменты проверки у меня работают постоянно.

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


                        Я переформулирую свой тезис. Раз речь о багах, и тем более если речь о багах, сути оно, тем более не меняет. При разработке чего-либо(т.е. при решении той или иной задачи, я это так называю), вы вырабатываете решение, концептуальное. У одной и той же задачи решений может быть несколько, со своими как плюсами так и минусами. И нередко приходится совмещать разные решения в одно. Чтобы качества добиться. Так вот если человек в принципе концептуально не умеет решать задачи, язык ему не поможет. Ибо в логике решения задач у него проблемы. А null dereference и иже с ними здесь всего лишь детали. А человек который умеет решать задачи, управиться с такими проблемами.

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


                        Скажите, а ассенизатор хорошо выполняет свою работу?

                        Наверное


                        Я говорил не о кругозоре, я говорил о профессионализме. Если вы умеете только что-то одно, вы не сможете решать более сложные задачи. Потому что не знаете ничего в смежных областях. А если и знаете то не факт что понимаете до конца, т.е. это уже опыт. А чтобы создать что-то реально новое, нужно знать очень много. Т.к. хорошие решения на самом деле, решаются не на одном уровне.

                        В штатах есть такое понятие, как overqualified. Не встречали?


                        Никак, согласен.

                        Все равны


                        Только, знание только С# тем более.

                        Но некоторые равнее :)


                        1. anatolymik
                          27.06.2019 14:02
                          -1

                          Окей, давайте не будем.
                          Покорнейше благодарю.

                          Вполне вероятен сценарий, где C# будет лучше за счет той же компактификации кучи, откуда кэш локалити и вот это все. Смотреть надо по ситуации.
                          Не даст он никаких преимуществ. Пара тройка максимум. Из всего спектра проблем. А компактификация и кэш локалити появились только потому что он на этапе своего рождения породил проблемы, которые необходимо было устранить. Иначе он бы не родился.

                          Они работают на эвристиках, и проверяют реальное изменение.
                          Плохо работают? 99,9% ловят, еще на этапе разработки.

                          Вы ведь понимаете, чем компиляция лучше дебага или даже тестов?
                          Проверки времени компиляции, не хуже и не лучше. Они просто есть. И их наличие упрощает разработку. Панацея?

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

                          Мое мнение такое, что если что-то можно автоматизировать, то это надо автоматизировать.
                          Придерживаюсь такого же подхода. Вот только что-то одно не панацея.

                          Или рейс кондишны
                          Рейс вам не один компилятор не покажет. Для этого ему уже надо понимать что вы пишите, а он не понимает. Когда начнет понимать, вы пойдете таксистом работать.

                          Например, нахождение нуллов.
                          Я вот не пойму что все носятся с этими нулами? Я допускаю эти ошибки. Но редко. В алгоритмах и подходах я ошибаюсь постоянно. Что компилятор уже не ловит. Складывается ситуация, что есть машина, а вожу плохо. Вывод — плохая машина. Интересные вы люди.

                          Лучше иметь компилятор, который отследит все случае, чем сидеть каждый раз руками с валгриндом и сравнивать.
                          Лучше, только никто еще этого не сделал. Для этого ему надо делать анализ кода, пока что и это плохо получается. И по факту, работать надо с тем что есть, а не мечтать о том, как было бы правильно. «Хочу чтобы было хорошо». Да я тоже хочу, дальше то что?

                          В штатах есть такое понятие, как overqualified. Не встречали?
                          А штаты эталон чего-то? И упомянутый термин тут к чему упомянут? Какое отношение он имеет к компиляции и удобству языков? Сказать нечего, но сказать надо. Я правильно понимаю?

                          И что до термина, придумали его эффективные менеджеры. Потому что им сиюминутно нужны бабки и чтобы поток их был стабильным. Не понятно как это происходит?

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

                          Про штаты вы мне можете не рассказывать, ровно как и про наше. Я про ИТ сферу. И по факту, эти менеджеры засерают мозги молодым специалистам, из-за чего они не вырастают. И в результате, вся сфера сейчас переживает падение качества. Причем стремительное. Старцы на пенсии, а молодые новаторы(я их так называю) ничего высрать не могут. Т.к. вечно недовольны инструментарием и мечтаю о лучшем загробном мире.

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

                          Но некоторые равнее :)
                          Я равнее, да.


      1. Ryppka
        27.06.2019 09:02

        Никогда не понимал тех, кому для признания в любви к языку А нужно ругать язык Б. Я люблю и C и Rust, но последний люблю за его возможности, а не за то, что в нем нельзя сделать трудно уловимые в C ошибки. Для меня это просто приятный бонус, за который приходится расплачиваться.


  1. ncr
    26.06.2019 10:06

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

    иллюзию полного и явного контроля.


    1. abondarev Автор
      26.06.2019 10:07

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


  1. Parondzhanov
    26.06.2019 13:20

    abondarev писал:

    Автор языка Оберон Николаус Вирт, вложил идею внесения ограничений, что существенно уменьшает риск написания небезопасного ПО. При этом с помощью доработки компилятора автор доклада, предлагает создавать образы, нацеленные на различные задачи и платформы. Доклад был мне очень близок, поскольку мы в Embox пришли к похожим идеям по ограничениям.

    Вы правы. Продуманные ограничения уменьшают риск написания небезопасного ПО.
    Вспомним. Эдсгер Дейкстра ввел ограничение, указав на опасность 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


    1. abondarev Автор
      26.06.2019 13:38

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


      1. staticmain
        26.06.2019 16:23

        >А в кулуарах даже рассуждали об использовании графических языков в АСУ для АЭС

        Недавно на хабре пролетало, что там графический язык программирования, который транслируется… в С.


        1. abondarev Автор
          26.06.2019 16:33

          Автор доклада является главным конструктором SCADA СУОК для АЭС
          Разговор был с автором доклада, у которого есть реальные внедрения.

          SCADA обычно состоит из минимум двух частей, РМО (рабочее место оператора) там используются мнемограммы, и рантайм управления. Вот рантайм может быть как на графических языках (Стандарт МЭК 61131-3 ), так и не на графических например на Обероне. Об этом можно например на хабре посмотреть тут


    1. mayorovp
      26.06.2019 18:06
      +1

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


      Дракон — это пример того, как не должен выглядеть визуальный язык программирования. Он неудобен, даже антиудобен. Программы на Драконе хороши тем, что их можно вставить в рамочку и повесить на стену книгу или презентацию в качестве иллюстрации. Но их очень сложно редактировать (когда я смотрел Дракон последний раз — там нельзя было перетащить блок в другое место, только удалить и создать заново), а ведь написание программы — это последовательность редактирований...


      Пример удобного визуального языка программирования — Scratch. Он точно так же, как и рекламируемый тут Дракон, формирует все управляющие конструкции целыми кусками — но при этом очень прост в редактировании.


      Исходя из этих соображений, в визуальном языке ДРАКОН (во имя безопасности потока управления) исключены опасные служебные слова, организующие поток управления: goto, break, continue, if, then, else, case, of, switch, while, do, repeat, until, for, foreach, loop, exit, when, last и т.д.

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


      PS нет смысла писать контактные данные под каждым комментарием — для них существует профиль пользователя


    1. anatolymik
      27.06.2019 12:02
      +2

      Не поленился и ознакомился по диагонали с драконом. Изучить надо не мало. Чтобы этим пользоваться. Вот и вопрос, чем проще то? Можно подумать блок-схемы читать удобнее. Дело привычки конечно. Но по-моему последовательно написанный текст будет информативнее. Да и транслятор этого не будет оптимальным.

      При использовании языка ДРАКОН функции, реализуемые указанными служебными словами, не записываются вручную, а формируются автоматически. Поэтому вероятность ошибок, вызванных разветвлениями и циклами, уменьшается или сводится к нулю.
      Ну не записали вы их вручную. Ну автоматически будет сгенерировано. Сгенерировано будет все равно исходя из того что вы задали на входе. А если вы на входе зададите неправильно, что ветвления правильными вдруг станут?

      Наибольшую вероятность появления ошибок создают разветвления и циклы.
      Вообще странное утверждение. Из которого следует чем сложнее алгоритм тем легче в нем ошибиться, потому что текста много. Можно подумать на драконе ничего для описания этого же алгоритма делать не надо будет. Ну будут у вас не такие ошибки как на классических языках. Будут другие. Разница то в чем?


      1. Siemargl
        27.06.2019 12:55

        Справедливости ради, графические языки (безотносительно дракона) гораздо удобнее в отладке, особенно когда не имеешь права поставить точку останова (любое работающее оборудование).


        1. Ryppka
          27.06.2019 13:04

          А еще они удобны при использовании систем контроля версий…


          1. mayorovp
            27.06.2019 14:34

            Надеюсь, это был сарказм.


            1. Ryppka
              27.06.2019 14:51
              +1

              Поверили?! )))


          1. Siemargl
            27.06.2019 16:59

            Это решаемая задача. И да, очень нужная — которую надо закладывать в инструментарий при его проектировании.


            1. Ryppka
              27.06.2019 19:47

              Пример решения?


              1. Siemargl
                27.06.2019 22:55

                Сейчас проекты экспортируются в текстовый/Иксмл формат и могут сравниваться.
                В принципе, я читаю например Роквелловские или Сименса текстовые диффы для релейки.

                Но в целом потому говорю, что нужно закладывать при проектировании — визуальному языку нужен и визуальный дифф.


                1. Ryppka
                  28.06.2019 08:55

                  Ох-ох, личный опыт с парой визуальных инструментов с xml-бэкендом и парой основанных на xml «языках» программирования терзает мою душу смутными сомнениями…


                1. mayorovp
                  28.06.2019 09:00

                  XML — это не столько решение, сколько костыль. Да, так делать можно — но в итоге разработчику нужно будет знать уже два языка (визуальный и его XML-представление). То есть визуальный язык перестает быть чем-то самостоятельным.


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


      1. Parondzhanov
        27.06.2019 22:54
        -1

        .


        1. anatolymik
          27.06.2019 23:08
          +1

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

          Относительно комментариев вроде:

          Функция заработала сразу! Более того, при переносе алгоритма в дракон-схему, я обнаружил, что у меня в ней была ошибка!
          А может, прошло время, и у человека в голове к моменту переноса все уложилось по полкам? А язык оказался не причем? Т.е. это было совпадение. Один случай на мой взгляд ничего не доказывает. Нужно вести статистику и из неё вычислять среднее значение.

          В тексте на Си её было незаметно. А при попытке перенести алгоритм на дракон-схему, ошибка стала не просто заметной — алгоритм в этом месте «не вырисовывался»!
          Чтобы разговор был предметным, хотелось бы увидеть реализацию на Си и на драконе. После можно уже что-то пытаться обсуждать.

          А пока что, на мой взгляд, это личное предпочтение и убеждение разработчиков графического языка. И в этом ничего плохого. Просто мне так видится ситуация.


        1. mayorovp
          27.06.2019 23:14

          Сергей Ефанов поясняет:
          ...

          Рад за Сергея, но все ещё не понимаю пользу Дракона для нормальных программистов.


          дракон-схема строится по правилам когнитивной эргономики, которая обнажает ошибки или лишает пользователя возможности сделать ошибку.

          Пустой набор слов, которые вместе ничего не обозначают.


          на основе визуального логического исчисления

          Не слышал о таком.


  1. anatolymik
    26.06.2019 18:07

    Ведь если посмотреть глубже, то даже в уже упомянутой дискуссии по поводу устаревания языка Си подразумевалось, что данный язык небезопасен и с его помощью очень просто “выстрелить себе в ногу”.
    Ну если на примере, то язык Си, изначально, не имеет представления о том, что такое стек. В контексте упомянутого ранее STACKLEAK, скорее виновата архитектура процессоров и трансляторы под них.

    Когда говорят о безопасности, надо понимать контекст. А конкретный пример чего-либо, сам по себе может еще ничего не доказывать.

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


    1. abondarev Автор
      26.06.2019 18:20

      Ну если на примере, то язык Си, изначально, не имеет представления о том, что такое стек.

      Ну это Вы загнули конечно. А где же тогда выделяются локальные переменные (память под них)? Или как по вашему происходит вызов функции, в смысле передача параметров?


      1. anatolymik
        26.06.2019 19:28
        +1

        А где же тогда выделяются локальные переменные (память под них)? Или как по вашему происходит вызов функции, в смысле передача параметров?
        Где я загнул? На уровне языка слово стек хоть где-то упоминается? А как оно реализовано аппаратно, язык и его модель не волнует. Все зависит от процессора, под который транслятор генерирует код.

        Я другой пример приведу, в процессорах Itanium стек данных и стек вызова развязан. А в будущем поколении процессоров Intel будет shadow stack. Что автоматически защищает от buffer overrun. Имеет ли язык Си к этому отношение? Что будет со стороны ОС сделано чтобы оно заработало? Надо ли будет дорабатывать компиляторы? По всем вопросам однозначно нет. А если так, возникает вопрос, как это получается, что появление аппаратного механизма делает абстрактный язык Си — безопаснее?

        Наверное у нас изначально разница в терминах. А значит и говорить не о чем.


        1. abondarev Автор
          27.06.2019 12:08

          А значит и говорить не о чем.

          Ну зачем Вы пишите, если говорить не о чем?

          Что будет со стороны ОС сделано чтобы оно заработало? Надо ли будет дорабатывать компиляторы? По всем вопросам однозначно нет.

          По этим двум вопросам однозначно, да!
          Вот мы тут портировали Embox под Эльбрус. Embox это ОС и там пришлось работу со стеком (при переключении контекстов) сильно замысловатым делать. Ну и конечно, как работать со стеком для конкретной архитектуры (и даже конкретного ABI) компилятор должен знать.

          По поводу синтаксиса языка Си в привязке к стеку. Вообще то все языки программирования неявно имеют представление об управлении памяти, и базовыми являются всего три конктрукции: выделение памяти на стеке, выделение памяти в куче, и глобальные переменные. Часть языков, вообще запретили всякие глобальные переменные, и оставили только стек и кучу.

          Но согласен, об организации данных в памяти прикладной программист зачастую не задумывается.


          1. anatolymik
            27.06.2019 13:02

            Ну зачем Вы пишите, если говорить не о чем?
            А зачем отвечаете?

            По этим двум вопросам однозначно, да!
            Со стороны ОС поддержать новый процессор. И делается это на языке Си который не знает ничего об этом. Компиляторы дорабатывать не надо. Ибо они не будут напрямую работать с shadow stack, учитывая его архитектуру.

            По поводу синтаксиса языка Си в привязке к стеку. Вообще то все языки программирования неявно имеют представление об управлении памяти, и базовыми являются всего три конктрукции: выделение памяти на стеке, выделение памяти в куче, и глобальные переменные.
            Управляет памятью, менеджер памяти конкретной операционной системы. Память на стеке(в свою очередь выделенный операционной системой при аппаратной поддержке процессора), выделяет сама программа, сгенерированная компилятором для конкретной архитектуры.

            Embox это ОС и там пришлось работу со стеком (при переключении контекстов) сильно замысловатым делать.
            А что вам мешало использовать встроенные средства языка Си для переключения контекста? Мы ведь уже выяснили что язык Си связан с термином стек.

            (и даже конкретного ABI)
            Нонсенс. Как получается что на MSVC я под Linux бинари собираю?

            Но согласен, об организации данных в памяти прикладной программист зачастую не задумывается.
            Я нигде этого не утверждал, поэтому не понимаю в чем вы со мной согласны.

            А если так, возникает вопрос, как это получается, что появление аппаратного механизма делает абстрактный язык Си — безопаснее?
            Вы лучше на этот вопрос ответьте. Как я уже сказал, по двум пунктам из трех — однозначно нет. Пояснения выше. Один пункт, это поддержка процессора. Но не языком и даже не его компилятором. Ваш опыт портирования ровным счетом ничего не доказывает.


            1. zloe_morkoffko
              27.06.2019 13:51
              +2

              А что вам мешало использовать встроенные средства языка Си для переключения контекста?
              Это какие? Лучше ссылочкой на пункт стандарта.


              1. anatolymik
                27.06.2019 15:08

                Коллега, это была ирония. Мне казалось, что в моих утверждениях видно какого мнения я придерживаюсь.


                1. abondarev Автор
                  27.06.2019 15:11

                  Вот именно, Вам казалось!


                  1. anatolymik
                    27.06.2019 16:12

                    Очень просто: студия при сборке бинарей под Linux использует gcc либо clang вместо родного cl.exe. Потому что cl.exe, внезапно, совсем не умеет создавать бинарники под linux, даже если там такой же amd64 что и на винде...
                    mayorovp Я это сделаю и при помощи cl.exe. И делал уже ранее. До того как все упомянутое вами появилось. А то что clang может генерировать под Windows, Android и так далее, ни на какие мысли не наталкивает?

                    Вот именно, Вам казалось!
                    Да? А может кое-кто просто печатного текста не понимает? И не может сопоставить что собеседник говорил до, и говорит сейчас?

                    Вам не кажется, что компилятор (бэкенд) должен быть доработан.
                    Мне не кажется, я знаю что не должен быть. А раз вам кажется, расскажите что и как должно быть доработано. Конкретно на пальцах, а не на уровне идеи. Я же говорю что не надо. Учитывая как работает shadow stack. Один раз включаем его на процессоре и все. Грубо говоря. Механизм спроектирован обратно совместимо.

                    Поскольку если архитектурной поддержки не требуется
                    Я такое утверждал? Более того, в контексте утверждения, не понятно о чем оно вообще. Чуть ниже объясняю.

                    почему не компилируется например под ARM с помощью gcc на x86
                    Встречное? почему на MSVC x86 компилируется и под ARM и под ARM64 и под x64?

                    Для чего вообще компилятору указывается ABI?
                    Компилятор так спроектирован. MSVC например, на, как вы говорите, ABI не завязан. Максимум instrinsic функции, которые реализует программист. Но сделано это для интеграции с операционной системой. Таких моментов не много. Только я подчеркну. Это все расширения языка. Расширения делает разработчик компилятора. И к стандарту оно отношения не имеет. Было время когда и расширений не было. Сделали их для удобства разработки для конкретных архитектур. И оно снова не имеет отношения к стандарту. Если в gcc этого не заложили, и вы на этом основании делаете выводы, то извините, проблема ваша.

                    Не очень понимаю как это делает язык Си безопаснее. Но систему в целом это делает безопаснее, что в конечном итоге и требуется!
                    Тогда вопрос, как тут язык оказался причем? Явно вы этого не утверждали, и стали оспаривать другой момент. Но тем не менее. Вы цитируете высказывания других людей без понимая дела?

                    Изначально претензия была к формулировке, о том что язык ничего не знает про стек.
                    Еще раз, укажите место в стандарте Си, где явно упомянута сущность стека. И если упомянута, то в каком контексте. Расскажите про встроенные функции языка для работы со стеком. Расскажите про встроенные функции для управления памятью. Из стандарта только. На язык.

                    Поскольку выделение переменной на стеке имеет локальную область видимости, и передача ссылки на эту переменную умирает при выходе из функции, как было показано в одном из коментариев о преимуществах языка rust.
                    Как область видимости доказывает существование стека? По-моему так компилятор интерпретирует исходный код. И не более того. В какой машинный код он транслируется делает какую-то разницу?

                    Как минимум не логична, поскольку связь со стеком, не означает, что можно им управлять и уж никак не означает, что такми образом можно встроенными средствами управлять переключением контекста.
                    Вопрос был риторическим. И наводящим. Но поняли вы неправильно.

                    надеясь на наличие мозгов у собеседника
                    Тебя прямым текстом послать? Или неявно? Хочешь мозгами померятся, пиши в личку. Посмотрим…


                    1. mayorovp
                      27.06.2019 16:16

                      Я это сделаю и при помощи cl.exe

                      Нельзя ли почитать об этом подробнее?


                      1. anatolymik
                        27.06.2019 17:38

                        Увы, нет. Дело было давно, лет 7 назад и делал я это самостоятельно. Что забавно, возникла такая потребность примерно в таком же контексте. Это был спор. Я потратил неделю и сгенерированный код cl.exe компилятором я заставил работать на Linux. Написал утилиту. Нужно было преобразовать PE в ELF. Ну и куча чего по мелочи. Делал на базе х86. Для х64 заморочек больше, например нужно согласовать модель вызова. Преобразовал все и заработало. Т.е. имеем сам факт, что код сгенерированный компилятором от студии, нормально работает и в Linux.

                        За выигранный спор, мне ничего не вернули. :) Объяснено это было тем что преобразование не считается. Все хотели из коробки. О чем я заранее предупредил, как я буду делать. И на момент посвящения в мои действия, у них не было никаких вопросов и возражений. Но когда появился результат…

                        А спор считаю выигранным потому, что противоположная сторона от меня ничего не потребовала, тем самым признавая меня победителем, но не желающая этого признавать.

                        Собственно примерно как сейчас, с другим собеседником.


            1. abondarev Автор
              27.06.2019 15:10

              А зачем отвечаете?

              Наверное Вы правы, не стоит отвечать на такое. Но попытаюсь еще раз объяснить свою позицию, надеясь на наличие мозгов у собеседника.

              Со стороны ОС поддержать новый процессор. И делается это на языке Си который не знает ничего об этом. Компиляторы дорабатывать не надо. Ибо они не будут напрямую работать с shadow stack, учитывая его архитектуру.

              Вам не кажется, что компилятор (бэкенд) должен быть доработан. Поскольку если архитектурной поддержки не требуется, почему не компилируется например под ARM с помощью gcc на x86? Для чего вообще компилятору указывается ABI?

              Нонсенс. Как получается что на MSVC я под Linux бинари собираю?
              Почему нонсенс, Вы же говорите под какую платформу хотите собрать, ну а если для Вас уже кто то сделал все остальное, то поверьте это не значит что компилятор языка ничего не знает об архитектуре под которую генериться код.

              А если так, возникает вопрос, как это получается, что появление аппаратного механизма делает абстрактный язык Си — безопаснее

              Не очень понимаю как это делает язык Си безопаснее. Но систему в целом это делает безопаснее, что в конечном итоге и требуется!

              Я бы не разбрасывался словами,
              Ваш опыт портирования ровным счетом ничего не доказывает.
              А более четко формулировал бы свои мысли. Изначально претензия была к формулировке, о том что язык ничего не знает про стек. Я утверждаю, что знает! Поскольку выделение переменной на стеке имеет локальную область видимости, и передача ссылки на эту переменную умирает при выходе из функции, как было показано в одном из коментариев о преимуществах языка rust.
              А вот Ваша фраза
              А что вам мешало использовать встроенные средства языка Си для переключения контекста? Мы ведь уже выяснили что язык Си связан с термином стек.
              Как минимум не логична, поскольку связь со стеком, не означает, что можно им управлять и уж никак не означает, что таким образом можно встроенными средствами управлять переключением контекста.


            1. mayorovp
              27.06.2019 15:40
              +1

              Нонсенс. Как получается что на MSVC я под Linux бинари собираю?

              Очень просто: студия при сборке бинарей под Linux использует gcc либо clang вместо родного cl.exe. Потому что cl.exe, внезапно, совсем не умеет создавать бинарники под linux, даже если там такой же amd64 что и на винде...


      1. 0xd34df00d
        27.06.2019 17:16
        +1

        Реализация, на каждый, эээ, стекфрейм (если выражаться в привычных терминах) выделяющая память из кучи при входе в функцию и удаляющая память при выходе, будет соответствовать стандарту С, но стека в смысле вот этой вот непрерывной растущей области с локальными переменными у неё не будет.


        1. abondarev Автор
          27.06.2019 17:41

          Конечно. Правда нужно еще хранить где то указатели на стекфреймы, но это мелочи.
          Я имел в виду, что есть разница в реальных компиляторах ( про которые не стоит забывать) при реализации: глобальных переменных, локальных переменных, статических локальных переменных, переменных выделенных на куче.
          А так, конечно согласен, стек (и отсюда почему большинство языков реализуют именно такую структуру) это только очень удобная реализация конкреной идеи распределения переменных и регистров. Но так как компилятор должен знать как устроена организация его локальных переменных, то я и написал, что это преувеличение.


          1. anatolymik
            27.06.2019 18:38

            Правда нужно еще хранить где то указатели на стекфреймы
            Первый элемент в выделенной куче — указатель на предыдущий фрэйм. Остальное локальные переменные.

            Не удивительно что портирование было настолько трудным. Титаническая работа. Намного сложнее чем делать самому.

            Но так как компилятор должен знать как устроена организация его локальных переменных, то я и написал, что это преувеличение.
            Я с самого начала сказал что язык Си, а не его компилятор. Это называется переобуваться в воздухе.


        1. abondarev Автор
          27.06.2019 18:58

          И, если бы автор оригинального коммента, написал, как Вы, что имеется в виду стандарт языка Си, а не фразы типа

          А значит и говорить не о чем.

          То никакого треша в комментах конечно бы не было!
          А так он понес прекрасную фигню, что компилятор не должен ничего знать об архитектуре процессора… Надеюсь он имел в виду, что используется промежуточный код типа llvm, но без этих пояснений, выглядит странно.


          1. anatolymik
            28.06.2019 18:54
            -1

            И, если бы автор оригинального коммента, написал, как Вы
            Этому есть название — подлизаться. Вроде ген. дир. А тут такое…

            А так он понес прекрасную фигню, что компилятор не должен ничего знать об архитектуре процессора…
            А что? Разве должен? Блин, а я не знал. Спасибо что просветили.

            Надеюсь он имел в виду, что используется промежуточный код типа llvm
            А че такое промежуточный код?


  1. Starl1ght
    27.06.2019 19:08
    +2

    Мы пишем драйвер на C++ (внезапно, даже 17). Да, у нас нет стандартной библиотеки, но тупо из-за наличия деструкторов в языке и инкапсуляции — разработка упрощается на порядки, никакие ресурсы не текут. Я не вижу смысла писать на чистом С вообще в любой разработке — даже крошечный сабсет С++98 выигрывает у чистого С по всем возможным статам (ну, кроме вероятного отсутствия компилятора под какой-нибудь некроконтроллер).


    1. Siemargl
      27.06.2019 23:06

      Ну про С++98 это перебор — на нем очень неудобно писать с STL (а без нее опять сырые указатели итп), а вот с++11/14 +линтер уже вполне безопасен и удобен по сравнению с другими условно безопасными языками.

      Единственный слаборешенный вопрос был с глобальной оптимизацией при наличии исключений, который привел в итоге к noexcept.

      Ну еще спорная производительность ARC, которая впрочем обходится минимизацией использования кучи.

      Впрочем последние две темы настолько тонкие, что в большинстве языков до обсуждения такого дело и не доходит — есть проблемы покрупнее =)


      1. Starl1ght
        28.06.2019 00:03

        В конкретно моем случае (полное отсутствие стандартной библиотеки в кернеле) — мы написали свои строки\умные указатели и тд и тп.


        1. abondarev Автор
          28.06.2019 10:44

          Речь шла о замене С/С++.
          С++ не используется в надежном ПО, не потому что нет компиляторов, а потому что менее предсказуемо, и можно уйти в область, смотри как я могу. Берем например стандарт MISRA. там вводятся различного рода ограничения на сложные конструкции. Программировать безусловно становиться тяжелее, но вот код более поддерживаемый и понятный, следовательно надежный.
          Вот Вам пришлось написать стандартную библиотеку (или какие то ее части), а кто сказал что там нет ошибок? Анализаторы кода стаонвятся сложнее, если использовать хитурые конструкции и так далее. А так да, на чем писать дело вкуса, и 17 плюсы (да и не только 17) конечно добавляют возможностей для разработчика по сравнению с чистым Си.


  1. Parondzhanov
    27.06.2019 23:23
    -1

    abondarev затронул важную проблему. Существует потребность в безопасных языках. Язык ДРАКОН — попытка создать безопасный визуальный язык.

    На практике используется, в частности, гибридный язык Дракон-Си, где Си служит целевым языком. При этом си-код не пишут вручную; он формируется автоматически на выходе дракон-схемы (комплекта дракон-схем). Вероятность ошибки уменьшается или сводится к нулю.

    Цель языка ДРАКОН — обеспечить безопасность потока управления.

    anatolymik писал:

    Вообще странное утверждение. Из которого следует чем сложнее алгоритм тем легче в нем ошибиться, потому что текста много. Можно подумать на драконе ничего для описания этого же алгоритма делать не надо будет. Ну будут у вас не такие ошибки как на классических языках. Будут другие. Разница то в чем?

    Разница в том, что на ДРАКОНе ошибок будет меньше или не будет совсем.
    Сергей Ефанов поясняет:
    Переписал на ДРАКОНе довольно запутанную функцию из реального проекта.

    Функция заработала сразу! Более того, при переносе алгоритма в дракон-схему, я обнаружил, что у меня в ней была ошибка! Эта функция работала уже довольно давно, не в одной сотне изделий. Ошибка не была фатальной, она возникала редко, и компенсировалась переподключением к серверу. Но она была!

    В тексте на Си её было незаметно. А при попытке перенести алгоритм на дракон-схему, ошибка стала не просто заметной — алгоритм в этом месте «не вырисовывался»!

    anatolymik писал:
    Ну не записали вы их вручную. Ну автоматически будет сгенерировано. Сгенерировано будет все равно исходя из того что вы задали на входе. А если вы на входе зададите неправильно, что ветвления правильными вдруг станут?

    Вероятность того, что вы на входе (т.е. в дракон-схеме) зададите неправильно, очень мала. потому что ДРАКОН срывает с ошибок «шапку-невидимку». Ошибки «сами лезут в глаза», поэтому пользователь (с большой вероятностью) их не сделает. На это есть две причины.

    1) дракон-схема строится по правилам когнитивной эргономики, которая обнажает ошибки или лишает пользователя возможности сделать ошибку.

    2) Графика дракон-схемы формируется программой дракон-конструктор, на основе визуального логического исчисления по правилам визуального логического вывода.

    Это значит, что (во избежание ошибок) пользователю языка ДРАКОН запрещено проводить линии между иконами дракон-схемы. Все линии автоматически проводит дракон-конструктор, а пользователь лишь управляет этим процессом, указывая какую икону (или макроикону) выбрать и в какую валентную точку ее вставить. Это вкратце.

    Разумеется, записывая текст внутри иконы, пользователь может ошибиться, но это будет ошибка ЛИНЕЙНОГО участка, которую сравнительно легко можно выявить и устранить.


    1. anatolymik
      28.06.2019 00:08
      +1

      Очень интересная форма высказывания. Сначала вы написали этот комментарий выше, потом удалили. Сейчас написали все тоже самое что было там. Вряд ли так можно заинтересовать.


    1. taujavarob
      28.06.2019 18:02

      Это старинная известная технология.

      Берутся типа «лучшие практики» и «рисование схемы» по которой и генерируется программа, использующая эти «лучшие практики».

      В Java это, к примеру — Eclipse Modeling Framework (EMF) (Не взлетел, но кто-то юзает).

      image