メモリを安全に効率よく使うための言語です。
Microsoft は 2019 年に、自社が毎年 CVE(= 公開された脆弱性 1 件ごとに付く、業界共通の番号) を割り当てる脆弱性のうち約 70% がメモリ安全の問題であると公表*しています。 Google も、Chromium の深刻な脆弱性(= 2015 年以降の 912 件)のうち約 70% がメモリ安全の問題であると公表*しています。 解放したものを使う、二度解放する、確保した外へ書く。根本はどれも同じです。
そして、米国当局が言語を移すよう求め始めました。
| いつ | どこが | 何を |
|---|---|---|
| 2022 年 11 月 | 米国 国家安全保障局(NSA) | C・C++ から、メモリの安全な言語へ移ることを推奨* |
| 2023 年 12 月 | 米国 CISA・NSA・FBI ほか | 製品の計画に「移行の道筋」を含めるよう要請* |
| 2024 年 2 月 | 米国 ホワイトハウス(ONCD・当時) | 同じく、メモリの安全な言語の採用を推奨* |
| 2024 年 10 月 | 米国 CISA・FBI | 重要インフラ向けの新製品を C・C++ で作ることを「悪い慣行」に挙げ、既存の製品には 2025 年末までのロードマップの公表を要請* |
| 2025 年 6 月 | 米国 CISA・NSA | メモリ安全な言語へ移るための手引きを公表* |
EU でも、サイバーレジリエンス法の脆弱性の報告義務が 2026 年 9 月 11 日に始まりました(= 全面適用は 2027 年 12 月 11 日)。言語の名指しはありませんが、趣旨は同じです。
移した所では、効果が出ています。Google は Android の新しいコードを Rust で書き、メモリ安全の脆弱性の割合を 2019 年の 76% から 2024 年に 24%、2025 年には 20% 未満に下げたと公表*しています。
ところが、C++ から離れられない現場があります。 既にある資産、必要な速度、動かす先の都合。「移れ」と言われても簡単には移れません。 上の 70% を公表した Microsoft 自身も、資産の多くを C++ のまま抱えていると思われます。
※ 当局が挙げる「メモリ安全な言語」は Rust・C#・Go・Java・Swift などで、*C++ は当局の例には挙げられていません。しかし当社は、検査を全部効かせた状態では同じ性質を満たすと考えています。
* 出所:Microsoft Security Response Center「A proactive approach to more secure code」(2019 年 7 月)
Chromium プロジェクト「Memory safety」(2015 年以降の深刻な脆弱性 912 件の分析)
NSA「Software Memory Safety」(2022 年 11 月・PDF)
CISA ほか「The Case for Memory Safe Roadmaps」(2023 年 12 月・PDF)
ONCD「Back to the Building Blocks: A Path Toward Secure and Measurable Software」(2024 年 2 月・PDF)
CISA・FBI「Product Security Bad Practices」(2024 年 10 月、2025 年 1 月改訂・PDF)
CISA・NSA「Memory Safe Languages: Reducing Vulnerabilities in Modern Software Development」(2025 年 6 月・PDF)
Google「Eliminating Memory Safety Vulnerabilities at the Source」(2024 年 9 月)
Google「Rust in Android: move fast and fix things」(2025 年 11 月)
AI にコードを書かせる作り方(= バイブコーディング)が広がっています。そこで生産性を決めるのは、人が確認する量です。 仕様どおりに動くかは走らせれば判りますが、メモリが安全かは走らせても判りません。人がコードを 1 行ずつ読んできたのは、このためです。
*C++ で書いた部分では、検査を全部効かせた状態で、メモリの安全は言語の側が保証します。 人が読んで確かめる理由が、ここでは無くなります。残るのは仕様どおりかの確認で、それは走らせて確かめられます。 詳しくは AI で書く の頁をご覧ください。
| C | 元の言語。メモリは、プログラマーが全て管理します。 |
|---|---|
| C++ | C に、クラスと RAII を足しました(= オブジェクトがスコープを抜けるとき、資源をその場で返します)。 |
| *C++ | RAII に加え、ランタイム(= YamatoMM)が、完全な回収とコンパクションを実行します。 |
C++ の RAII は、共有された所有(= shared_ptr)の循環参照と、断片化は解消しません。 そこを担うのが YamatoMM です(= YamatoMM とは)。Rust の所有権と借用は、寿命を静的に決める別の方法です(= ただし循環参照は Weak で手動で解消します)。 C++23 では、規格から自動回収の仕組みが削除されました。
C++ に目的ごとの記述を足したものは、以前から幾つもあります(= CUDA C++ は GPU の並列、C++/CLI は .NET、Objective-C++ は Objective-C との混在)。 いずれも C++ を否定せず、上に載せています。*C++ もそうで、その目的を「メモリ管理」に置きました。 当初の C++ が C へ変換するプログラムであったように、元の言語をそのまま使いながら、足りない部分だけを言語の側で補いました。
※ RAII は「Resource Acquisition Is Initialization」の略で、資源の確保と解放をオブジェクトの寿命に括り付ける考え方です(= 詳しくは YamatoMM とは)。
※ C++23 で削除されたのは、規格に書かれていた自動回収の取り決めです(= 到達可能かを処理系へ知らせる関数の一組)。この取り決めに従って実際に回収を行うコンパイラや実行環境は、1 つも現れませんでした。形だけが残っていたものが、使われないまま外されました。
C++ でオブジェクトを扱うとき、確保と解放はプログラマーの仕事です。 *C++ では、その仕事を言語の側に移しました。 オブジェクトの寿命を管理するのが、*C++ のランタイム YamatoMM です。
スマートポインタも所有権管理も、その手作業を洗練させたものです。 Java や C# のように「寿命を考えない」ところまでは至っていません。
| 方法 | 寿命を考えるのは誰か |
|---|---|
| 確保と解放を自分で書く | プログラマー自身 |
| スマートポインタ | プログラマー自身どの型のポインタを選ぶか、循環参照をどう切るかを決めるのはプログラマーです。 |
| 所有権で管理する | プログラマー自身誰が所有するかを、プログラマーが設計します。 |
| *C++ | 仕組みの側 |
メモリの安全は、3 段構えで守ります。寿命は仕組みが決め、不正な操作は検査で止め、危ない書き方は書けなくします。
| 基盤 | オブジェクトの寿命は、仕組みが管理します。解放したものを使う、二度解放する、返し忘れる。この 3 つは、寿命をプログラマーが管理しているために起きます。*C++ では起きません。検査ではなく、構造です。 |
|---|---|
| 検査 | 不正な操作は、検査を効かせた姿では、その瞬間にその場所で止めます。null を辿る、確保した外へ書く(境界)、型を取り違える、2 つのスレッドが同時に書く(競合)。未初期化のフィールドを読むことは、確保のたびに 0 で埋めて起きなくします(ゼロクリア。局所変数も同じです)。Java や C# にもある 4 つと、*C++ 独自の競合の検出です。 |
| 制約 | 書けないから、起きません。寿命を任せた型では、実体を直接置く、生ポインタで持つ、データを持つ基底を 2 つ以上継承する、自分で delete する、の 4 つが書けません。この形で、スコープを抜けた実体を指し続ける、切り捨て、ポインタ演算、基底のずれ、new と delete の対の不一致が消えます。検査ではなく、構造です。 |
頁の冒頭に挙げた 3 つ(= 解放したものを使う、二度解放する、確保した外へ書く)は、前の 2 つが基盤で消え、3 つ目が境界の検査で止まります。 検査はテストモードでは全部効かせ、リリースモードでは要らないものを外せます。詳しくは、安全性 のページをご覧ください。
そして、寿命を仕組みが管理すると、もう 1 つできることがあります。回収と、コンパクションです(= YamatoMM とは)。
メモリ管理を言語の側に持たせる試みは、これまで 2 極に分かれていました。 Java や C# のように実行環境が寿命を管理する側と、Rust のようにコンパイラが安全を証明する側です。 前者は寿命を任せられますが、止まる時間を自分で管理することと、C++ の資産の多くを手放しました。後者はネイティブのまま安全を保証しますが、任せることと、既存の C++ をそのまま使うことを手放しました。 *C++ は、その間に立ちます。前者から「任せる」を、後者から「ネイティブのまま」を受け取り、両者が手放した「いまの C++ のまま」を残しました。
次の表は、C++ の資産を抱えた現場、という前提で比較しています。自動でメモリを管理する仕組みには、5 つの課題があります。 いまの C++ をそのまま使えるか。安全性では、同時アクセスをどう扱うか、検査を選び直せるか。効率性では、止まる時間が読めるか、隙間を解消できるか。 既にあるものは、どれかが欠けています。
| 言語 | いまの C++ をそのまま使えるか | 安全性 | 効率性 | ||
|---|---|---|---|---|---|
| 競合をどう扱うか | 検査を選び直せるか | 止まる時間が読めるか | 隙間を解消できるか | ||
| C++ | そのものです | 何もしません | 一括でなら効かせられますC++26 の標準ライブラリの強化モードで、境界と null の検査をまとめて効かせます。1 つずつではありません。 | 止まりません | 解消しません |
| C#(.NET) | 使えませんC++/CLI で書き直した所だけ移ります。 | 壊れません値は不定になりますが、メモリの安全は保たれます。検出はしません。 | 外せません常に効きます。 | 構成で狭められます自分で呼べますが、呼ばない時にも止まります。止まる長さの目標値は指定できず、待ち時間を抑えるモードと、一定の量までは止めない設定があります。 | 解消します大きなオブジェクトの領域(LOH)は、既定では詰めません。 |
| C++/CLI | ほぼ使えますネイティブの C++ と混ぜて書けます。回収に載せる所は ref class と gcnew で書き直します。Windows の .NET 上に限られます。 | 壊れません値は不定になりますが、メモリの安全は保たれます。検出はしません。 | 外せません常に効きます。 | 構成で狭められます.NET の回収そのものです(= C# の欄と同じ)。 | 解消します大きなオブジェクトの領域(LOH)は、既定では詰めません。 |
| Java(JVM) | 使えません | 壊れません値は不定になりますが、メモリの安全は保たれます。検出はしません。 | 外せません常に効きます。 | 構成で狭められます自分で呼べますが、呼ばない時にも止まり、長さは目標値の指定までです。 | 解消します |
| Go | 使えませんcgo で C の関数は呼べますが、C++ のオブジェクトの寿命には効きません。 | 何もしませんテスト用の検出器(-race)はありますが、テストで走った経路の分だけです。走らなかった経路は見つけません。競合があるとメモリの安全は崩れます。 | 外せません常に効きます。境界だけはコンパイラのオプションで一括で外せますが、1 つずつではありません。 | 短いですが、決められません回収は並行で、自分で呼ぶことも止めることもできますが、長さを渡す手段はありません。 | 解消しません動かさない回収です。 |
| Swift・Objective-C の ARC | 取り込めますObjective-C++ で混ぜて書けます。C++ のクラスの寿命には効きません。 | Swift 6 では、コンパイル時に検査しますSwift 6 の言語モードにした所だけです。C++ のクラスの中は対象外です。 | まとめてなら外せます-Ounchecked で一括です。1 つずつではありません。 | 読めますただし、解放が連鎖すると伸びます。 | 解消しません |
| Rust | 使えませんC++ と混ぜて書き、移す所だけ書き直せます(bindgen / cxx)。移した所は Rust です。借用検査を C++ に足す Safe C++ も、安全な範囲は書き直しが要り、同じ扱いです。 | コンパイル時に排除します書けばコンパイルが通りません。既存の C++ には後から掛けられません。 | 外す設定はありません検査の無い操作を unsafe で 1 か所ずつ許します。 | 止まりません | 解消しません所有権により寿命が静的に決まるため隙間が出にくく、断片化はアロケータ(jemalloc / mimalloc)で抑える設計です。 |
| Fil-C※ | ほぼ使えます多くは無改造か小さな修正で動くと公式が書いています(= sqlite や tmux は無改造。CPython / OpenSSH / Emacs は修正して動いています)。 | 壊れません競合してもメモリの安全は保たれます。検出も停止もしません。 | 外せません全て有効で固定です。 | 止まりません並行で回収します。上限をプログラマーが決める形ではありません。 | 解消しません動かさない回収です(= 並行を簡単にするため)。 |
| *C++ | ほぼ使えます管理しない側はそのまま動きます。管理する側だけ *C++ で書き直します。出力は標準の C++ で、いまは macOS 上の clang でビルドしています。 | 見つけたら、実行を停止します囲んでいないアクセスは、見つけたら、その場で実行を停止します。 | 5 つを 1 つずつ外せますテストモードでは全て有効、リリースモードで外します。 | 読めます毎周期の回収とコンパクションは、渡した時間に収めます。上限の外は 2 つで、参照が無くなった瞬間の解放の連鎖と、確保が間に合わないときの一度の回収です。 | 解消します |
※ 安全性の 1 つ目の欄は、寿命ではなく「同時アクセス」の話です。
自動でメモリを管理しても、2 つのスレッドが同じ場所を同時に書けば値は壊れます(= メモリの安全が保たれる言語でも、値は不定になります)。
排他の印(= ロック)で囲めば消えますが、囲んでいない所は、何も検出されません。
Rust はコンパイル時に排除し、*C++ は実行時に見つけて、実行を停止します。消える不具合の範囲はほぼ同じで、違いは時期です。既存の C++ に後から掛けられるのが *C++ の違いです。
※ 安全性の 2 つ目の欄は、安全の検査(= null・境界・ゼロクリア・型・競合)を、速さのために 1 つずつ外せるかです。安全性 のページに詳しく書きました。
※ 隙間の解消(= コンパクション)は、オブジェクトが動く分、参照の仕組みに代価があります(= 効率性の 3)。断片化をアロケータで抑える方法もあり、C++ や Rust はその方式です。
当社が調べた範囲では、5 つが同時に揃うものは他にありませんでした。 いまの C++ をそのまま使いながら効率性の 2 つを同時に成立させることが極めて難しく、C++ の上で、実行時の検査を言語の一部として持ち、部品ごとに 1 つずつ選び直せる形にしたものも見つかりませんでした(= コンパイラの検査器は種類ごとに選べますが、テスト時に付ける物です。委員会のプロファイルは、C++29 に向けて審議中です)。 しかし、*C++ は実現しました。 止まる時間をどう収めるかは、YamatoMM の 取り扱い方法 に書きました。
※ 当社が調べた範囲です(= 2026 年 9 月 13 日時点。公開されている資料に基づきます)。他の言語(= Python など)も調査しましたが、「いまの C++ をそのまま使えるか」と効率性の 2 項目、合わせて 3 つのうち 2 つ以上が欠けているため省きました。併せて、C++ に自動回収を持ち込む試みも調べています(= Boehm GC / Bartlett の mostly-copying とその系譜の CMM・Ravenbrook MPS / Chromium の Oilpan / Unreal Engine の GC / Apple の Objective-C の GC / C++11 で入り C++23 で削除された取り決め)。いずれも、その 3 つのうち 2 つ以上が欠けています。Boehm GC は C/C++ をそのまま回収しますが、オブジェクトを動かしません。Bartlett の系譜と MPS はオブジェクトを動かしますが、型ごとに走査の関数を書く必要があります。MPS には止まる時間の目安の指定もありますが、収める保証はありません。Oilpan がコンパクションするのは、コレクションの中身だけです。Apple の GC は OS X 10.8 で非推奨となり、参照カウント(= ARC)へ移りました。C/C++ を変えずに断片化を減らすアロケータ(= Mesh、2019 年)もありますが、オブジェクトを動かさずにページを重ねる形で、完全なコンパクションではありません。C++ にも、AddressSanitizer や ThreadSanitizer、UndefinedBehaviorSanitizer のように実行時に検査する手段はあり、種類ごとに選べます。テスト時に付けるもので言語の一部ではなく、競合の検出はテストで走った経路と、記録の窓に入った分に限られます。C++26 では、標準ライブラリの境界などの検査を一括で効かせる強化モードが規格に入りました(= 2026 年 3 月に完成)。種類ごとではありません。C++ の後継言語の試み(= Google の Carbon)も見ていますが、C++ を書き換える形のため、当社の軸とは別に置いています。表に載せた Fil-C は 2024 年からの実装で、既存の C/C++ を、多くは無改造か小さな修正でコンパイルし、メモリ安全にします。動く所は Linux(= x86_64 / ARM64)のみです。ハードウェアの側で既存の C/C++ を守るものもあります。CHERI(= ポインタに範囲と権限を持たせ、機械の側で検査します)と、メモリの札(= ARM の MTE。Android は Pixel 8 以降が対応し、Apple は iPhone 17 から OS の中核で常時効かせています)です。どちらも、回収も隙間の解消も無く、対応した機械が要ります。C++ でない言語には、検査を種類ごとに外せるもの(= Ada、Nim、D)や、時間の上限を持つ回収(= Java の実時間向けの実装、ゲームエンジンの逐次回収)がありますが、いまの C++ のオブジェクトをそのまま扱う物ではありません。
※ 他の言語や処理系についての記述は、公開されている資料に基づく当社の調べで、誤りや古くなった箇所が含まれる可能性があります。お気づきの点は license@kuusoukagakutech.co.jp へお知らせください。確認のうえ、修正いたします(= 記述内容について)。
メモリ安全の話で、最も名前が挙がるのは Rust です。 Rust は、解放したものを使う、二度解放する、これらをコンパイルの時点で止めます。確保した外へ書くことは、実行時に止めます。競合も、コンパイルの時点で排除します。 設計として正しく、私たちも優れた仕組みだと考えています。 ただし、寿命の設計を書くのはプログラマーで、コンパイラはそれをチェックする形です。*C++ は、その設計そのものを仕組みが引き受けます。 検査を全部効かせた状態では、*C++ で書いた部分で消える不具合の範囲は、Rust とほぼ同じです。Rust はコンパイル時に、*C++ は実行時に止めます。
Rust が対象の外に置いているものもあります。互いに参照し合って解放されない状態(= 循環参照)は所有権の外にあり、どこで切るかはプログラマーが決めます。 *C++ では、YamatoMM が回収します。
いまの *C++ は、Rust の代わりではありません。 新しく書くもののうち、OS やドライバのように低い層を書くものは、Rust が向いています。 いまある C++ の資産を、書き換えずに使い続けたい所に、*C++ は向いています。 C++ をそのまま使いながら、寿命の管理と実行時の検査を後から足す。それが *C++ の位置です。