/note/tech

Why Fighter Jets Ban 90% of C++ Features

要約:

■ 1. 航空宇宙ソフトウェアの歴史的背景

  • 1996年6月4日、Ariane 5ロケットが打ち上げ36秒後に爆発した。原因は64ビット浮動小数点数を16ビット整数に変換する際の未処理例外であり、5億ドルが一瞬で失われた。
  • F-35の設計者はこの教訓から、JSF C++標準のAVルール208で「例外を使用してはならない」と規定した。
  • 1970年代初期、F-4 Phantomには実質的にソフトウェアが存在せず、爆撃コンピュータは歯車とカムの箱であった。
  • F-14 Tomcatプロジェクトで、Garrett AI Researchが世界初のマイクロプロセッサを開発した。これはIntel 4004より数年早く、かつ高速であったが、1998年まで機密扱いであった。
  • F-14の可変翼設計には手動操縦では対応できず、約2500行のマイクロコードで多項式方程式を処理した。これが航空機における最初の本格的なソフトウェアとなった。

■ 2. 軍用ソフトウェアの言語戦争

  • 初期のソフトウェア時代、米陸軍、空軍、海軍はそれぞれ異なるコーディング標準を持っていた。
  • 空軍はJovial(Jules's Own Version of the International Algorithmic Language)を使用していた。
  • 海軍はF-18でCMS2という独自言語を採用し、互換性は皆無であった。
  • 機上ソフトウェアの量は指数関数的に増加した:
    • F-16Aで12万5000行
    • B-1で100万行
    • F-35で900万行
  • 当時450以上の異なるプログラミング言語が使用されており、適切な標準が存在しなかった。
  • 国防総省は全ての言語を置き換える高級言語としてAdaを開発した。
  • Adaの使用は約15年間義務付けられ、使用しない場合は不可能であることを証明する必要があった。

■ 3. C++への移行とJSF標準の誕生

  • 1990年代、航空宇宙分野ではAdaが主流であったが、同時期にインターネット、Windows 95が登場し、多くのゲームがC++で動作していた。
  • 当時、コンパイラは有料で数千ドルもしたが、C++とGCCは無料であり、学生はC++を学習した。
  • Lockheed MartinはF-35プロジェクトでAdaの代わりにC++の使用を国防総省に提案した。
  • 提案者は「法律を破ることを承認してください」という内容を提示したことになる。
  • Lockheed Martinは純粋なC++ではなく、言語を制限する計画を用意していた。
  • C++の作成者Bjarne Stroustrup自身がJSF規則の策定に関与したことを認めている。
  • JSF標準は特定の機能を外科的に除去することで、強力な言語を認証可能なコードに変換する。
  • JSF標準は完全に公開されており、オンラインで閲覧可能である。
  • Joint Strike Fighterという名称は、Lockheed Martinだけでなく、多数の防衛企業、政府、複数の国が協力して開発したことを示している。

■ 4. JSF C++標準の主要な制約事項

  • 例外処理の禁止(AVルール208):
    • 例外は予測不可能な制御フローを生成する
    • Ariane 5の事故は値のオーバーフローではなく、未処理例外が問題であった
    • Bjarne Stroustrup自身は現代のC++例外処理を支持しているが、当時のツールの成熟度では応答時間を保証できなかった
    • JSF標準では例外の代わりにリターンコードを使用する
    • リターンコードは呼び出し元関数に処理を委ねる
  • 再帰の禁止(AVルール119):
    • 関数は直接的または間接的に自身を呼び出してはならない
    • 再帰はスタックオーバーフローの可能性を生む
    • 各再帰呼び出しは新しいスタックフレームを作成する
    • 再帰の最大深度が不明な場合、メモリ使用量の上限を知ることができない
    • 反復的アプローチで置き換える必要がある
  • メモリ割り当ての制限(AVルール206):
    • 初期化後のメモリ割り当てと解放を禁止する
    • 動的メモリ割り当てはコードに予測不可能性をもたらす
    • メモリマネージャーが利用可能なメモリを見つけるのにかかる時間が不明である
    • 十分なメモリが利用可能かどうかも不明である
    • ヒープ上の割り当てはフラグメンテーションを引き起こす
    • 解決策として最大データサイズをハードコードし、事前割り当てを行う
  • 循環的複雑度の制限(AVルール3):
    • 関数の循環的複雑度は20を超えてはならない
    • 循環的複雑度は関数内の決定パスの数を示す
    • if文、whileループ、forループ、論理演算子(andやor)、switch文などがカウントされる

■ 5. 実装例とシミュレーション

  • XPlane 12フライトシミュレータとF-35Bを使用したデモンストレーションが実施された。
  • マルチファンクションディスプレイ(MFD)がF-16スタイルで構築され、リアルタイムの飛行データに接続された。
  • XPlaneのWeb APIを通じてライブ飛行データが配信される。
  • フロントエンドはPython、バックエンドはC++で実装された。
  • JSF標準に準拠したC++コードで密度高度計算、飛行データ、旋回計算、V-NAVデータ、風計算などが実行される。
  • 非準拠コードでは未処理例外が発生し、プログラムがクラッシュするシナリオが示された。
  • 準拠コードではリターンコードを使用し、呼び出し元関数がエラーを適切に処理する。
  • 初期のF-35はMotorola G4 Power PCプロセッサベースのミッションコンピュータを使用していた。これは2003年のAviation Todayの記事で公開された情報である。

■ 6. JSF標準の影響と現代への継承

  • F-35 C++標準の原則は他の分野や標準にも広がった。
  • NASAのF-Prime標準は2017年に公開され、メモリ割り当て禁止、例外処理禁止、再帰禁止という同様の制約を持つ。
  • 自動車業界にもコーディング標準が存在する:
    • MISRAとAutoSAR(Automotive Open System Architecture)
    • AutoSARはC++14標準の影響の一つとしてJSFを名指しで参照している
    • AutoSARではスマートポインタが許可されるなど、より現代的なC++の機能が利用可能である
  • 自動車は車輪付きコンピュータと言える存在になっている。
  • BMW、Ford、Toyotaなど主要な自動車メーカー全てがAutoSARに依存している。
  • これらの言語安全性は数十年前に国防総省が下した決定に基づいている。

■ 7. 結論と提言

  • Bjarne Stroustrup自身、JSF標準の策定委員会の一員であったが、現在はC++ Core Guidelinesの使用を推奨している。
  • 現代のC++は過去20年間で進化し続けており、JSF標準は当時の素晴らしいエンジニアリング成果であったが、より新しく安全な現代的C++を使用すべきである。
  • JSF標準は歴史的に重要かつ興味深い部分であり、一見の価値がある。
  • JSF標準はC++のような複雑な言語を、重要なインフラストラクチャに安全な予測可能なものに変換することに成功した。
  • 最も賢いプログラマーであることが重要なのではなく、どの要素を「飛行前に取り除く」かを知る規律を持つことが重要である。

関連: