
Rust製exeがWindows 7で0xC0000005(Access Violation)になる本当の理由――「エントリポイントが無い」のに“正しいエラー”が出ないワケ
Rustの最近のバージョンでビルドしたWindows向け実行ファイルを、古いWindows(例:Windows 7)で起動すると「0xC0000005(Access Violation)」で即死する。しかも本来よく見る「Entry point not found」や「互換性がありません」という分かりやすいローダーエラーではない。PEヘッダ上の最小OSバージョン(例:NT 6.0=Vista相当)とも噛み合わず、余計に“怪しく”見える——。
結論から言うと、原因はだいたい「OS非対応なAPI(エントリポイント)を、MSVCのCRT(Cランタイム)やローダー周辺のどこかが想定外の形で踏んでしまい、結果として“アクセス違反”に見えている」ことです。Rust側のコードが悪いというより、起動前後に動く“周辺部品”の都合が大きい、という話になります。 The Rust Programming Language Forum+1
- Rust製exeがWindows 7で0xC0000005(Access Violation)になる本当の理由――「エントリポイントが無い」のに“正しいエラー”が出ないワケ
まず押さえる:0xC0000005は「メモリアクセス違反」だが、必ずしも“あなたのmainが暴走した”とは限らない
0xC0000005(STATUS_ACCESS_VIOLATION)は、ざっくり言えば「存在しない/権限のないメモリに触った」例外です。多くの人はアプリ本体のバグを疑いますが、Windowsではプロセスがmainに到達する前に、以下のような層が大量に動きます。
-
PEローダー(依存DLLのロード、インポート解決、TLS、各種初期化)
-
MSVCのランタイム(CRT初期化、スレッド/例外/ロケール等の準備)
-
“APIセット”やフォワーディング(KERNEL32→KERNELBASE等)の解決
-
追加のセキュリティ機構・互換レイヤー・サイドバイサイド(WinSxS)周辺
このどこかが想定外の状態になれば、ユーザーコードが一行も走らないのに0xC0000005で落ちることは起こり得ます。フォーラムでも「ロードの段階が複雑で、どの段階で失敗したかによって見えるエラーが変わる」趣旨の指摘が出ています。 The Rust Programming Language Forum
「本来はEntry point not foundで止まるはず」なのにAccess Violationに見える理由
Windowsの“王道”の失敗パターンは、インポートしている関数がOS側に無い場合に、起動時に「手続きエントリポイントが見つからない」系で止まることです。実際、Windows 7で問題になりやすい例として GetSystemTimePreciseAsFileTime がよく挙がります(Windows 8以降で提供されるAPIで、Windows 7にはありません)。Rustや関連ツールでこのシンボルが原因になる話題・報告は複数あります。 GitHub+2Reddit+2
ではなぜ「見つからない」ではなく「アクセス違反」に“化ける”ことがあるのか。代表的には次の3系統です。
1) 遅延ロード(Delay-load)や動的解決(GetProcAddress)で「NULL関数ポインタ呼び出し」になる
インポートテーブルで静的に解決されるなら、ローダーが早い段階で検出して“それっぽいエラー”を出しやすいです。
しかし、CRTや周辺ライブラリが遅延ロードやGetProcAddressで動的に取る実装だと、「取れなかった→戻り値NULL→そのまま呼んでAV」という事故が起こり得ます。これは設計ミスというより、歴史的経緯や互換分岐の不足で“そうなることがある”タイプです。
2) MSVCのCRT(UCRT/VCRuntime)が、古いOSでの前提を捨てている
Rustの *-pc-windows-msvc は、リンク時にMSVC系ランタイム(UCRT等)へ依存します。Windows 7は公式サポート対象から外れており、ツールチェーン側が「古いOSでの動作」をあえて担保しない方向に寄っています。Rust自体も、Windows 10以上を最低要件に引き上げる方針を明確にしています。 blog.rust-lang.org+2GitHub+2
このとき問題になるのは「Rustの標準ライブラリが直接そのAPIを呼ぶ」だけではなく、起動前のCRT初期化が新しめのAPI前提で動いてしまう点です。フォーラム返信でも「MicrosoftのCRT初期化が怪しい」「WinSxSやUCRT周りで段階によってエラーが変わる」といった方向性が示唆されています。 The Rust Programming Language Forum
3) 互換性チェック(PEヘッダのMinimum OS)=“実際に必要なAPI”ではない
PEヘッダの OS version や Subsystem version は、互換性判断の一材料ですが、それだけで「そのOSで必ず動く」保証にはなりません。
リンクされたランタイムや依存DLLが、より新しいAPIを要求していれば、ヘッダがVista相当でもWindows 7で落ちます。しかも失敗の見え方は「どの層が、どの形で呼び出したか」に依存します(結果がAVになる場合もある)。
じゃあ技術的には「何が不足」しているのか:よくある欠損の実態
Windows 7での非互換は、だいたい次のどれかに収束します。
-
KERNEL32.dll / KERNELBASE.dll などに存在しない関数を要求している
例:GetSystemTimePreciseAsFileTime など(典型例として多く言及される) GitHub+1 -
UCRT/VC++再頒布可能パッケージの前提が崩れている(未導入・古い・OS側が想定外)
-
APIセット(api-ms-win-*)やフォワード先解決が、OS世代差で思った通りに動かない
-
起動直後の初期化(スレッド/例外/ロケール/タイマ等)が新OS前提になっている
そして“見える症状”は、必ずしも「エントリポイントが無い」ダイアログとは限らず、0xC0000005のような雑な落ち方になることがある、というのがポイントです。
対処の現実解:Windows 7で動かしたいなら「ツールチェーン戦略」を変える
Rust 1.76以降でWindows 7/8/8.1が公式サポート外になった流れは明確で、Windows 10以上が前提になっています。 GitHub+1
それでも“事情があってWin7で動かす”なら、実務的な選択肢は次の通りです(再現性が高い順)。
A) Rustツールチェーンを「Windows 7対応が残っていた世代」に固定する
「最後のWin7対応」として語られることが多いのはRust 1.75周辺です。プロジェクト側でMSRV(最低Rustバージョン)を決め、CIもそのバージョンで固定します。 GitHub+2Reddit+2
B) *-pc-windows-gnu(MinGW系)でビルドする
MSVCランタイム依存を避け、MinGWのCランタイムを使うことで、古いOSでの“起動直後の地雷”を回避できるケースがあります。フォーラム返信でもこの方向が提案されています。 The Rust Programming Language Forum
C) UCRT/VC++再頒布可能パッケージを最新化する(ただし限界あり)
不足しているのがランタイム側のコンポーネントであれば改善することがあります。ただし、OSに存在しないカーネルAPIを要求している場合は、再頒布可能パッケージを入れても根本解決にはなりません(APIはOS本体の機能なので)。
どこで失敗しているかを“確定”させる観測ポイント
「Access Violationに見える」問題は、原因が同じでも出方が違うことがあります。切り分けの定番は次です。
-
イベントビューア(Windowsログ→アプリケーション)で障害モジュールや例外コードの詳細を見る
-
**Dependencies(Dependency Walker後継)**やdumpbin等でインポートを確認する
-
可能なら ProcMon で起動直後に読み込もうとしているDLLや失敗箇所を見る
-
-C target-featureやリンク設定変更よりも、まず「どのDLL/どの関数が欠けているか」を特定する
特に「欠けているエントリポイント名」が分かれば、原因はほぼ確定します。Windows 7では GetSystemTimePreciseAsFileTime が“犯人”として挙がりやすい、というのもこの文脈です。 GitHub+1
まとめ:怪しいのはRust本体より「起動前の部品」。AVは“結果”であって“原因名”ではない
-
0xC0000005は「アクセス違反」だが、Rustのmain以前(ローダー/CRT初期化)でも普通に起こる
-
Windows 7はRustの公式サポート対象から外れており、MSVCランタイムや依存APIが新OS前提になりやすい blog.rust-lang.org+1
-
“本来のエントリポイント不足”が、遅延ロードや初期化経路の都合でAVとして表面化することがある The Rust Programming Language Forum
-
Win7で動かすなら「古いRustに固定」か「windows-gnuでビルド」など、ツールチェーンの方針転換が現実解 The Rust Programming Language Forum+1
「正しいエラーが出ない」のは気持ち悪いですが、Windowsの起動シーケンスは層が厚く、失敗の見え方が一定ではありません。重要なのは、Access Violationという“症状名”に引っ張られず、「どのDLLのどの関数が欠けているか」を観測して、ビルド方針(MSVCかGNUか、Rustのバージョン固定か)を決めることです。