30 Punkte von GN⁺ 2025-12-09 | Noch keine Kommentare. | Auf WhatsApp teilen
  • Ein Video erklärt, warum Kampfjet- und Raketen-Software, bei der ein einzelner Bug bei Mach 1 fatale Folgen haben kann, den Großteil der C++-Funktionen entfernt und nur vorhersagbaren Code übriglässt
  • Es fasst die Geschichte zusammen, wie der mechanische Bombencomputer der F-4, der lange geheime Mikroprozessor der F-14 und die militärischen Sprachkämpfe rund um Jovial, CMS-2 und Ada sowie die Code-Explosion zur Forderung nach einer einheitlichen sicheren Sprache und strengen Standards führten
  • Es demonstriert anhand echten Codes, wie der im Zuge der F-35-Entwicklung entstandene JSF-C++-Standard, mit dem Lockheed den Einsatz von C++ statt Ada durchsetzte, Ausnahmen, Rekursion und dynamische Speicherallokation verbietet und sie durch Rückgabecodes, Schleifen und vorab reservierten Speicher ersetzt
  • Außerdem wird gezeigt, dass die frühen Missionscomputer der F-35 eine PowerPC-basierte Architektur nutzten, und mithilfe einer Verbindung von X-Plane 12 mit einem selbstgebauten MFD verglichen, wie sich Code, der die JSF-Regeln verletzt, und regelkonformer Code tatsächlich im Flug unterschiedlich verhalten
  • Abschließend wird dargestellt, dass der JSF-Standard später zu Sicherheitsstandards wie NASA F-Prime, MISRA und AutoSAR führte und dass heute ein Ansatz auf Basis dieses Erbes mit C++ Core Guidelines und modernem C++ passender ist

Vorstellung des Vortragenden

  • Ein Entwickler, der C++-Code für Luft- und Raumfahrtsysteme geschrieben und Demos für die Luftwaffe durchgeführt hat
    • Er erklärt das Thema auf Grundlage realer Erfahrung mit C++ in Systemen mit hohen Sicherheitsanforderungen
    • Als Demo-Umgebung nutzt er ein selbstgebautes MFD (Multifunction Display), bestehend aus X-Plane 12, einer Web-API, einer Python-UI und einem C++-Backend

Flugsoftware und Umgebungen, in denen Fehler nicht toleriert werden

  • Bei gewöhnlichen Anwendungen endet ein Crash oft mit einem Neustart, aber bei Mach-1-Kampfjets und Raketen bedeutet ein einziger Fehler unmittelbar eine Katastrophe
    • Mit dem Satz „Bei Mach 1 gibt es keine Zeit, auf den Garbage Collector zu warten“ wird die Echtzeitanforderung betont
    • Wenn eine einzige fehlerhafte Zeile zu tödlichen Folgen führen kann, muss bereits die Auswahl der Sprachfeatures selbst als Sicherheitsmechanismus dienen
  • Als typisches Beispiel wird die Explosion der Ariane 5 im Jahr 1996 genannt
    • Beim Umwandeln eines 64-Bit-Gleitkommawerts für den horizontalen Bias in eine 16-Bit-Ganzzahl trat eine Ausnahme auf, die nicht behandelt wurde
    • Die Sprache erzeugte den Fehler normgerecht, aber das System konnte die Ausnahme nicht verarbeiten, was zur sofortigen Zerstörung einer 500-Millionen-Dollar-Rakete führte
  • Ausgehend von diesem Fall entschied sich das F-35-Designteam für den Ansatz, Sprachfeatures selbst abzuschneiden, um denselben Fehler nicht zu wiederholen

Geschichte militärischer Software und der Sprachenkrieg

  • In der Frühzeit von Kampfflugzeugen wie der F-4 Phantom gab es praktisch noch keine Software
    • Der Bombencomputer war eher eine präzise mechanische Vorrichtung aus Zahnrädern und Nocken, und der „Code“ war die Form der Metallnocken selbst
  • Beim geheimen Marine-Luftüberlegenheitsprojekt VFX (F-14 Tomcat) änderte sich die Lage
    • Erst später wurde bekannt, dass Garrett AiResearch einen Mikroprozessor für die F-14 entwickelt hatte, der der als „erster Mikroprozessor“ bekannten Intel 4004 aus Lehrbüchern zeitlich vorausging
    • Um den Schwenkflügel der F-14 optimal zu steuern, war ein leistungsfähiger Mikroprozessor nötig, auf dem rund 2500 Zeilen Microcode für Polynom-Berechnungen liefen
  • Danach begann durch die Einführung unterschiedlicher Sprachen bei den Teilstreitkräften ein Wildwuchs an Programmiersprachen
    • Die Luftwaffe nutzte Jovial (Jules Own Version of the International Algorithmic Language), eine Sprache aus der ALGOL-Familie
    • Die Marine wollte die Sprache der Luftwaffe nicht verwenden und setzte in der F-18 auf CMS-2
    • Durch unterschiedliche Sprachen und Hardware-Architekturen wurde Code-Wiederverwendung und Verifikation nahezu unmöglich
  • Gleichzeitig wuchs die Softwaregröße pro Flugzeug exponentiell
    • Als Zahlenbeispiele nennt der Vortrag etwa 125.000 Zeilen für die F-16A, etwa 1 Million für die B-1 und rund 9 Millionen für die moderne F-35
    • Eine Untersuchung des Verteidigungsministeriums ergab, dass mehr als 450 Programmiersprachen im Einsatz waren und kaum eine davon über einen vernünftigen Standard verfügte

Die Durchsetzung von Ada und ihre Grenzen

  • Um dieses Chaos zu beheben, entwickelte das Verteidigungsministerium mit Ada eine einheitliche Hochsprache und verpflichtete Projekte stark zu ihrer Nutzung
    • Wer in neuen Projekten kein Ada einsetzen wollte, musste nachweisen, warum es mit Ada unmöglich war; andernfalls war kein Vertragszuschlag zu bekommen
  • Ada wird als Sprache vorgestellt, die für Bereiche mit hohen Anforderungen an Sicherheit und Zuverlässigkeit sehr gut geeignet ist
    • Besonders hervorgehoben wird das Design zur Gewährleistung von Speicher- und Typsicherheit in sicherheitskritischen Systemen wie der Luft- und Raumfahrt
  • In den 1990er-Jahren zeigte sich jedoch eine zunehmende Entkopplung von der Realität
    • Gleichzeitig dominierten Internet, Windows 95 und kommerzielle Spiele auf Basis von C++ den Mainstream
    • Studierende und Entwickler wandten sich statt teurer Ada-Compiler ganz natürlich dem kostenlosen GCC und C++ zu
    • Ada-Compiler kosteten mehrere tausend Dollar und waren für Einzelpersonen schwer zugänglich, wodurch auch der Pool an Ada-Fachkräften schrumpfte

F-35 und die Entstehung des JSF-C++-Standards

  • Die F-35 (Joint Strike Fighter) wurde von Anfang an als Flugzeug mit sehr hohem Softwareanteil konzipiert
    • Komplexe Berechnungen wie Sensor Fusion wurden zu einem Kernbestandteil des Betriebs
  • Lockheed Martin schlug dem Verteidigungsministerium vor, für diese Anforderungen den Einsatz von C++ zu erlauben
    • Das lief faktisch auf die Bitte hinaus, die bisherige Ada-Pflicht zu lockern, und dafür musste ein Weg gefunden werden, die Risiken von C++ zu beherrschen
  • Dabei wirkte auch der C++-Erfinder Bjarne Stroustrup als Berater an der Gestaltung der JSF-C++-Regeln mit
    • Er erklärte, direkt an der Ausarbeitung beteiligt gewesen zu sein, und sagte selbst, dass er diesem Standard gegenüber daher „voreingenommen sein könnte“
  • Die Kernidee ähnelt dem Gedanken hinter einem „remove before flight“-Tag
    • Wie ein Tag, der vor dem Start entfernt werden muss, werden gefährliche C++-Funktionen auf Sprachebene entfernt, sodass nur eine vorhersagbare Teilmenge verwendet wird
    • So sollte Ada-ähnliche Sicherheit erreicht werden, während Entwickler dennoch einen Teil der Ausdrucksstärke von C++ nutzen können

Reale Hardware und die GameCube-Analogie

  • Die frühen F-35-Blöcke verwendeten Missionscomputer auf Basis von Motorola-G4-PowerPC-Prozessoren
    • Diese Information wurde unter anderem in einem Artikel von Aviation Today aus dem Jahr 2003 veröffentlicht
  • Auch der GameCube nutzt einen Prozessor aus der PowerPC-Familie, was als interessante hardwareseitige Verwandtschaft auf Befehlssatzebene angeführt wird
    • Für eine exaktere Generationseinordnung wäre eine andere Konsole näherliegend, aber zum Verständnis des Prinzips reicht der GameCube-Vergleich aus

JSF-C++-Demo-Umgebung: X-Plane 12 + MFD

  • Auf Basis von X-Plane 12 und dem F-35B-Addon von AOA Simulations wird eine Flugsimulator-Umgebung aufgebaut
    • Über die neue Web-API von X-Plane werden Flugdatendaten in Echtzeit abonniert und im MFD angezeigt
  • Das Frontend besteht aus Python, während das Backend als C++-Plugin umgesetzt ist; so werden regelkonformer und regelverletzender Code direkt verglichen
    • Angezeigt werden unter anderem Höhe, Geschwindigkeit, Wind, Flight Envelope und Navigationsdaten als Ergebnisse von C++-Berechnungen
  • Im Flug wird absichtlich nicht standardkonformer C++-Code, der Ausnahmen wirft, ausgeführt, sodass das MFD abstürzt und Probleme im Flug entstehen; anschließend wird schrittweise gezeigt, wie die Anwendung der JSF-Regeln dies behebt

Die drei zentralen Einschränkungen von JSF: Ausnahmen, Rekursion, dynamischer Speicher

  • Der JSF-C++-Standard betont drei zentrale Einschränkungen: Ausnahmen (Exceptions), Rekursion und dynamische Speicherallokation
    • Zusätzlich wird auch eine Obergrenze für die Cyclomatic Complexity von Funktionen festgelegt

1) Verbot von Ausnahmen – AV Rule 208

  • JSF AV Rule 208: „Exceptions shall not be used“
    • Schlüsselwörter wie try, catch und throw werden vollständig verboten
  • Der wichtigste Grund ist die Nichtdeterministik des Kontrollflusses
    • Wie bei Ariane 5 kann das gesamte System unvorhersehbar zusammenbrechen, wenn bei einer Ausnahme das Handling fehlt oder das Timing nicht stimmt
  • Bjarne steht moderner C++-Exception-Handling grundsätzlich positiv gegenüber, erklärt aber, dass zur Zeit der JSF-Entwicklung Werkzeugreife und garantierte Echtzeitfähigkeit für eine Unterstützung noch nicht ausreichten

    „JSF++ ist für Hard-Real-Time- und sicherheitskritische Anwendungen (Flugsteuerung) gedacht. Wenn Berechnungen zu lange dauern, können Menschen sterben, und mit Ausnahmen lassen sich Antwortzeiten nicht garantieren.“

  • Statt Ausnahmen verwendet JSF Rückgabecodes
    • Im Beispiel einer Berechnung der Druckhöhe werden für verschiedene Fehlersituationen unterschiedliche Rückgabecodes gesetzt, die der Aufrufer auswertet
    • So kann die aufrufende Seite auch bei Berechnungsfehlern oder Zeitüberschreitungen einen sicheren „Fehlerzustand“ darstellen, ohne dass das gesamte Programm abstürzt

2) Verbot von Rekursion – AV Rule 119

  • AV Rule 119 verbietet, dass eine Funktion direkt oder indirekt sich selbst aufruft, also Rekursion
    • Da sich bei jedem rekursiven Aufruf ein neuer Stack-Frame aufbaut und die maximale Tiefe schwer zu begrenzen ist, steigt das Risiko eines Stack Overflow
  • Als Beispiel dient der Binomialkoeffizient, der bei der Berechnung eines Ausweichflughafens im Flugplan verwendet wird
    • In der nicht standardkonformen Version wird eine rekursive Implementierung in der Form C(n, k) = C(n-1, k-1) + C(n-1, k) verwendet
    • Dadurch hängt die Aufruftiefe von der Eingabe ab, was die Vorhersage der Speicherobergrenze erschwert
  • In der JSF-konformen Version wird dieselbe Berechnung auf eine iterative Implementierung mit Schleifen umgestellt
    • Der Code ist länger und weniger elegant, liefert aber ohne Selbstaufrufe dasselbe Ergebnis
    • Dadurch lassen sich maximale Aufruftiefe und Speicherverbrauch statisch deutlich leichter abschätzen

3) Verbot dynamischer Speicherallokation – AV Rule 206

  • AV Rule 206: Nach der Initialisierung werden weder Speicher angefordert noch freigegeben
    • Heap-Allokationen zur Laufzeit über new, delete oder internes new über Smart Pointer sind verboten
  • Der Grund sind zwei zentrale Probleme
    • Heap-Allokation bringt eine zeitliche Nichtdeterministik mit sich, weil unklar ist, wie lange sie dauert
    • Wird der Heap fragmentiert, kann trotz noch freier Gesamtkapazität die Zuweisung scheitern, weil kein großer zusammenhängender Block mehr gefunden wird
  • Als Beispiel wird nicht standardkonformer Code gezeigt, der für die Berechnung von Böen eine Verlaufspuffer für IAS (Indicated Airspeed) mit std::unique_ptr und einem dynamischen Array anlegt
    • Dabei wird zur Laufzeit ein neues Array angefordert und damit gegen die JSF-Regeln verstoßen
  • Die JSF-konforme Version verwendet stattdessen ein Array fester Größe mit konstant definierter Maximalgröße
    • Mit Konstanten wie MAX_IAS_HISTORY wird die Größe festgelegt, der Speicher einmalig bei der Initialisierung reserviert und anschließend nur der Index rotiert
    • Dadurch entstehen im laufenden Betrieb keine weiteren Allokationen mehr, was Vorhersagbarkeit bei Zeit und Speicher sicherstellt

4) Obergrenze für Cyclomatic Complexity – AV Rule 3

  • AV Rule 3 schreibt vor, dass die Cyclomatic Complexity einer Funktion 20 nicht überschreiten darf
    • Die Funktionsdeklaration zählt selbst mit 1 Punkt, und if, while, for, switch sowie logische AND/OR erhöhen die Komplexität jeweils um 1
  • An der iterativen Implementierung des Binomialkoeffizienten wird gezeigt, wie jedes if, jede logische Operation und jede for-Schleife den Komplexitätswert erhöht
    • Da mit steigender Komplexität Test, Verifikation und Analyse schwieriger werden, ist die Einhaltung einer Obergrenze ein zentrales Ziel des Standards

Das JSF-Erbe: NASA F-Prime, MISRA, AutoSAR

  • Die Ideen des JSF-C++-Standards verbreiteten sich später in andere sicherheitskritische Bereiche
    • Das Flugsoftware-Framework F-Prime der NASA wurde 2017 veröffentlicht und teilt Regeln wie Verbot dynamischer Speicherallokation, Verbot von Ausnahmen und Verbot von Rekursion
  • Auch in der Automobilindustrie setzte sich ein ähnlicher Trend fort
    • Standards wie MISRA C++ und AutoSAR (Automotive Open System Architecture) entstanden und legten Sicherheitsregeln für Fahrzeugsoftware fest
    • Es wird erwähnt, dass die AutoSAR-C++14-Guidelines ausdrücklich auf JSF Bezug nehmen, was zeigt, dass der Einfluss von JSF bis in die Automotive-Software reicht
  • Moderne Autos sind faktisch „Computer auf Rädern“, sodass solche Sprach-Teilmengen und Coding-Regeln eine zentrale Grundlage für Sicherheit bilden

Fazit: Woran sollte man sich heute orientieren, wenn man C++ verwendet?

  • Der JSF-C++-Standard wird als technische Leistung dargestellt, die für ihre Zeit eine komplexe Sprache auf eine vorhersagbare Teilmenge reduzierte und so Sicherheit auf dem Niveau von Flugsteuerung in Kampfjets ermöglichte
  • Gleichzeitig empfiehlt Bjarne Stroustrup heutigen Entwicklern, sich an den C++ Core Guidelines und modernem C++ zu orientieren
    • Denn Sprache und Toolchain von C++ haben sich in den vergangenen Jahrzehnten weiterentwickelt, und für Features wie Ausnahmen und Smart Pointer gibt es heute oft sichere Einsatzumgebungen
  • Trotzdem bleibt JSF ein wichtiges Beispiel für die Denkweise, eine Sprache nicht durch Ergänzen, sondern durch „Entfernen“ zu kontrollieren
    • Die abschließende Botschaft lautet: Nicht was man hinzufügt, sondern was auf die „remove before flight“-Liste gehört, ist der Kern des Entwurfs sicherheitskritischer Systeme

Noch keine Kommentare.

Noch keine Kommentare.