Почему использование шаблона C++ не рекомендуется в космической/излучаемой среде?

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

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

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

Ответ 1

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

Почему использование шаблона C++ не рекомендуется в космической/излучаемой среде?

Эта рекомендация является обобщением C++ правил кодирования MISRA C и правил Embedded C++, а также рекомендаций DO178C и относится не к излучению, а к встроенным системам. Из-за радиационных и вибрационных ограничений встроенное оборудование любого ракетно-космического компьютера должно быть очень небольшим (например, по соображениям экономии и энергопотребления, это больше -in компьютер power- система Raspberry Pi-like, чем большой x86) серверная система). Космические закаленные чипы стоят в 1000 раз дороже, чем их гражданские аналоги. А вычисление WCET на компьютерах со встроенным пространством все еще является технической проблемой (например, из-за проблем, связанных с кэшем ЦП). Следовательно, выделение кучи не одобряется в критических системах safety- критического встроенного программного обеспечения -in (как бы вы справились с условиями нехватки памяти в них? Или как бы вы доказали, что у вас достаточно ОЗУ для всех случаев реального времени выполнения? )

Помните, что в мире критического программного обеспечения safety- вы не только каким-то образом "гарантируете" или "обещаете", и, конечно, оцениваете (часто с некоторыми умными вероятностными рассуждениями) качество вашего собственного программного обеспечения, но также и всех используемых программных инструментов. создать его (в частности: ваш компилятор и ваш компоновщик; Boeing или Airbus не будут менять свою версию кросс-компилятора GCC, используемого для компиляции их программного обеспечения для управления полетом, без предварительного письменного разрешения, например, от FAA или DGAC). Большинство ваших программных инструментов должны быть как-то одобрены или сертифицированы.

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

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

Посмотрите также на Frama-Clang и CompCert и обратите внимание на следующее:

  • C++ 11 (или ниже) - ужасно сложный язык программирования. У него нет полной формальной семантики. Достаточно опытных людей в C++ всего несколько десятков во всем мире (вероятно, большинство из них в своем стандартном комитете). Я способен кодировать в C++, но не объяснять все тонкие угловые случаи семантики перемещения или модели памяти C++. Кроме того, C++ требует на практике многих оптимизаций для эффективного использования.

  • Очень сложно создать безошибочный компилятор C++, в частности, потому что C++ практически требует хитрой оптимизации и из-за сложности спецификации C++. Но текущие (такие как недавние GCC или Clang) на практике довольно хороши, и у них есть немного (но все еще некоторые) остаточных ошибок компилятора. Еще нет CompCert++ для C++, и для его создания требуется несколько миллионов евро или долларов (но если вы можете собрать такую сумму, пожалуйста, свяжитесь со мной по электронной почте, например, по [email protected] Мое рабочее письмо). И индустрия космического программного обеспечения чрезвычайно консервативна.

  • Трудно сделать хороший распределитель памяти кучи C или C++. Кодирование - это вопрос компромиссов. В качестве шутки рассмотрите возможность адаптации этого распределителя кучи C к C++.

  • Доказательство свойств безопасности (в частности, отсутствие условий гонки или неопределенное поведение, такое как переполнение буфера во время выполнения) связанного с шаблоном кода C++ все еще во 2кв2019 немного опережает современное состояние статического анализа программ Код C++. Мой черновой технический отчет Бисмона (это черновой вариант Н2020, так что, пожалуйста, пропустите страницы для европейских бюрократов) содержит несколько страниц, объясняющих это более подробно. Помните о теореме Райса.

  • тестирование встроенного программного обеспечения всей системы C++ может потребовать запуска ракеты (а-ля Ariane 5, испытательный полет 501 или, по крайней мере, сложные и тяжелые эксперименты в лаборатории). Это очень дорого. Даже тестирование на Земле марсохода отнимает много денег.

Подумайте об этом: вы кодируете какое-то критическое встроенное программное обеспечение safety- (например, для торможения поездов, автономных транспортных средств, автономных беспилотников, большой нефтяной платформы или нефтеперерабатывающего завода, ракет и т.д.). Вы наивно используете какой-то стандартный контейнер C++, например, std::map<std::string,long>. Что должно произойти из-за нехватки памяти? Как вы "докажите" или, по крайней мере, "убедите" людей, работающих в организациях, финансирующих космическую ракету стоимостью 100 миллионов евро, в том, что ваше встроенное программное обеспечение (включая компилятор, использованный для его сборки) достаточно хорошо? Правило десятилетней давности должно было запрещать любое динамическое распределение кучи.

Я говорю не о сложных стандартных библиотеках, а о специально созданных пользовательских шаблонах.

Даже это трудно доказать или, в более общем смысле, оценить их качество (и вы, вероятно, захотите использовать свой собственный распределитель внутри них). В пространстве кодовое пространство является сильным ограничением. Таким образом, вы должны скомпилировать, например, g++ -Os -Wall или clang++ -Os -Wall. Но как вы доказали -or просто test- все тонкие оптимизации, выполненные -Os (и они специфичны для вашей версии GCC или Clang)? Ваша организация, финансирующая космос, попросит вас об этом, поскольку любая ошибка во время выполнения во встроенном космическом программном обеспечении C++ может привести к сбою миссии (прочитайте еще раз о неудаче первого полета Ariane 5, закодированной на некотором диалекте Ады, который в то время имел "лучшее "и" более безопасная "система типов, чем C++ 17 сегодня), но не смейтесь слишком над европейцами. Boeing 737 MAX с его MACS представляет собой похожий беспорядок).


Моя личная рекомендация (но, пожалуйста, не принимайте это всерьез. В 2019 году это скорее каламбур, чем что-либо еще), подумайте о кодировании вашего встроенного программного обеспечения в Rust. Потому что это немного безопаснее, чем C++. Конечно, вам придется потратить от 5 до 10 млн. Евро (или MUS $) через 5 или 7 лет, чтобы получить прекрасный компилятор Rust, подходящий для космических компьютеров (опять же, пожалуйста, свяжитесь со мной профессионально, если вы способны потратить это много на свободном программном обеспечении Compcert/Rust как компилятор). Но это всего лишь вопрос разработки программного обеспечения и управления проектами программного обеспечения (подробнее читайте как задания Mythical Man-Month, так и Bullshit, также помните о принципе Дилберта: он в равной степени относится к индустрии космического программного обеспечения или индустрии встроенных компиляторов, так что что-нибудь еще).

Мое твердое и личное мнение состоит в том, что Европейская комиссия должна финансировать (например, через Horizon Europe) проект, подобный бесплатному программному обеспечению CompCert++ (или даже лучше, Compcert/Rust) (и для такого проекта потребуется более 5 лет и более 5 топ-класса, PhD исследователи). Но в возрасте 60 лет, к сожалению, я знаю, что этого не произойдет (потому что идеология ЕС -mostly, вдохновленная политикой Германии в отношении очевидного reasons-, все еще является иллюзией конца истории, поэтому H2020 и Horizon Europe На практике это в основном способ реализации налоговых оптимизаций для корпораций в Европе через европейские налоговые убежища), и это после нескольких частных дискуссий с несколькими участниками проекта CompCert. Я с сожалением ожидаю, что DARPA или NASA с большей вероятностью будут финансировать какой-то будущий проект CompCert/Rust (чем финансирует его ЕС).


NB. Европейская индустрия авионики (в основном Airbus) использует гораздо более формальные методы, чем североамериканская (Boeing). Следовательно, некоторые (не все) модульные тесты избегаются (поскольку заменены формальными доказательствами исходного кода, возможно, с помощью таких инструментов, как Frama-C или Astrée), ни один из них не был сертифицирован для C++, только для подмножества C, запрещающего выделение C динамической памяти. и ряд других особенностей С). И это разрешено DO-178C (не предшественником DO-178B) и одобрено французским регулятором DGAC (и, я полагаю, другими европейскими регуляторами).

Ответ 2

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

template<class T>  fun(T t){
   do_some_thing(t);
}

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

Вторая проблема заключается в том, что:

fun(b);

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

Ответ 3

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

  • шаблоны "компилируются", то есть создаются и генерируются кодом, как и любая другая функция/член, и для них не существует специфического поведения. Как будто они никогда не существовали;

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