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


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


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


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


Таким образом, возникают, казалось бы, взаимоисключающие и не разрешимые противоречия:


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

Но ключевым моментом в предыдущем абзаце является фраза "казалось бы".


Введение в проблематику


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


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


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


И именно этот момент (новые правила лексики) фактически и нарушают обратную совместимость со всем старым легаси кодом С++!


Возможна ли безопасная разработка на С++?


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


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


Я не рассматриваю реализацию дополнительного синтаксического анализа за счет сторонних приложений (статических анализаторов, например, на базе Clang-Tidy), так как любое внешнее по отношению к компилятору решение, всегда будет содержать как минимум один существенный недостаток — необходимость синхронно поддерживать и использовать одни и те же режимы компиляции исходных текстов программ, что для С++ может быть очень не тривиальной задачей с его препроцессором.

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


  1. lieff
    12.01.2025 15:33

    1. rsashka Автор
      12.01.2025 15:33

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


      1. lieff
        12.01.2025 15:33

        В RFC пишут об обратном: "The proposed Safe C++ should be a pure subset of ISO C++ except few ignorable pragma and attributes. So that other compilers which don’t support the extension can compile the codes accepted by Safe C++."

        https://discourse.llvm.org/t/rfc-a-clangir-based-safe-c/83245

        Я правда тоже пока не gонял как они собираются делать совместимость в сложных примерах а не приведенных демках. Но вроде как это объявлено целью.


        1. rsashka Автор
          12.01.2025 15:33

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


          1. lieff
            12.01.2025 15:33

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


  1. Jijiki
    12.01.2025 15:33

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

    Скрытый текст
    vec2 t(vec2 x)
    {
      return x-1*2+100;//не заработает в С
    }

    тут как бы напрашивается момент где начинается граница ошибок

    если стандарты языка С++, то вроде просто надо выбрать стандарт и в него компилировать (но я когда писал компилировал старый код в 23 стандарт и пользовался не всеми преимуществами стандарта - писал на шаблонах + наследование, ну стандартный С++ как мне кажется, с доступными штуками - там вроде всё тривиально, а вот по статье по ссылке где пишут что С++ не безопасен я смотрел ее и никогда не думал так писать - двоякое ощущение), мне лично показалось когда видел ту статью что так можно где угодно ошибки найти

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

    Windows.h линкуется собирается с 23 стандартом и вы даже brush сможете вызвать и воспользоваться и другими вызовами, где легаси, где опасность, в чем там проблемы я пока не понял

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


  1. kozlyuk
    12.01.2025 15:33

    Предложенный подход в пределе означает реализовать borrow checker для C++ (имеется в виду анализатор схожей мощности). Вряд ли много компаний-пользователей компилятора способны написать такое сложное расширение (это мягко говоря). Если оно будет написано, скорее всего, удобнее будет интегрировать эти наработки в апстрим, чтобы упростить поддержку.


    1. Jijiki
      12.01.2025 15:33

      а какой конкретный пример есть на этот счет? может сервер - web не сможет работать с обращениями и будет что сбой? или что произойдёт, что конкретно в race condition плохого у С++?

      может легаси не соберётся в чем там проблема можно пример?

      у меня есть пример возможно плохой

      		thread = SDL_CreateThread(TestThread, "TestThread", (void *)NULL);
      
      		SDL_WaitThread(thread, &threadReturnValue);

      я запускал 2-3 окна игроки рендерились

      это код дедикейтед сервера


  1. kovserg
    12.01.2025 15:33

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


  1. Explorus
    12.01.2025 15:33

    не уверен насчет совместимости, но некоторые предложения от Саттера уже были
    https://isocpp.org/files/papers/P3081R0.pdf


    1. rsashka Автор
      12.01.2025 15:33

      Это решает одну и туже задачу с помощью одних и тех же инструментов (аннтоации).

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


  1. JordanCpp
    12.01.2025 15:33

    Возможна ли безопасная разработка на С++?