Skip to content

MS_Support64bit

nishi_74322014 edited this page Aug 12, 2026 · 1 revision

64bit対応

概要

本ページでは、64bit プラットフォーム移行に伴うアプリケーションの
環境移行、ポーティング移行の作業範囲を扱います。

  • WOW64は、64bit プラットフォーム上で Win32 アプリケーションを
    実行する、エミュレーションレイヤー・サブシステム。
  • 64bit 版システムファイルを納めた \System32 ディレクトリに対応する形で
    32bit 版ファイルを格納した \SysWOW64 ディレクトリのコンポーネントを
    利用して動作する。
  • これにより、32bit アプリケーションはそのまま
    64bit プラットフォーム上でも動作する。

補足(紛らわしい命名): System3264bit
SysWOW6432bit である。
直感に反するが、これは「既存の 32bit アプリが System32 という
パス文字列をハードコードしている」ことへの互換性配慮による。
32bit プロセスから C:\Windows\System32 を開くと
自動的に SysWOW64 にリダイレクトされる
(ファイル システム リダイレクト)。
リダイレクトを避けたい場合は C:\Windows\Sysnative という
疑似パスを使う。

  • 構造
    • WOW64 ホストプロセスによって予約された 4GB の仮想空間に
      32bit ABI のコードを読み込み、
    • そこで発生した Win64 API に変換可能な API 呼び出しを変換して、
      Win64 サブシステムに伝達する。
    • 構造体の変換は自動的に行われ、Win32 側では現在動作している OS が
      32bit システムか、64bit システムかを意識する必要は全くない。
    • ユーザーモードで動作するコンポーネント群は 32bit 版と 64bit 版が用意され、
      例えば OLE などは 32bit で閉じた範囲で動作できる。
    • 64bit 版で提供されるコードは単一のソースから、
      32bit 版と 64bit 版両方をそれぞれコンパイルして作られているため、
      機能的差異は無い。

通常のアプリケーション

以下に、WOW64を使用する際の注意点を記述する。

  • 32(64)bit の ABI から 64(32)bit の ABI を呼べないので
    どちらかに揃える。

    WOW64では 32bit の ABI に揃える(ABI:実行ファイルやライブラリ)。

  • デバイスドライバ類は WOW64を利用できないので
    64bit に対応した物を準備する。

  • レジストリ リダイレクトおよびレジストリ リフレクション、
    ファイル システムのリダイレクトの機能がある。

  • ファイルや変数への参照が原因で、問題が発生する場合がある。
    (システム変数、環境変数、KNOWNFOLDERID 値、および
    Sysnative エイリアスを含むファイル システム パス フォーム)

  • その他、WOW64の制限事項

    • アドレス空間は既定で 2.0GB である。
    • 16bit プロセスの実行はサポートされない。
    • 仮想 DOS マシン(VDM)API は無効化される。
    • AWE(Address Windowing Extensions)、スキャッター/ギャザー I/O、
      書き込み追跡など、ページサイズに依存する API は、IPF 上では利用できない。
    • PAE(Physical Address Extension)は、IPF 上では利用できない。
    • DirectX、ハードウェア アクセラレータ API は、IPF 上ではサポートされない。
      ※ IPF:Itanium Processor Family
    • COMを経由した 32bit ABI のコードと 64bit ABI のコードとの
      相互な呼び出しが禁止されている。

移行メモ(最新化): 上記のうち Itanium(IPF)に関する制限は
現在は無関係
である。Itanium は 2021年に完全に終息し、
Windows Server 2008 R2 が最後の対応 OS であった。
現在「64bit Windows」といえば x64(AMD64)Arm64 を指す。

なお Arm64 Windows では、WOW64 に加えて

  • x86 エミュレーション(32bit x86 アプリを実行)
  • x64 エミュレーション(Windows 11 以降)
  • ARM64EC(x64 と Arm64 のコードを 1 プロセスで混在させる ABI)

という仕組みがあり、「ビット数」に加えて「命令セット」も
考慮が必要になっている。

補足(「相互に呼べない」の要点): 太字にした 「32bit プロセスと 64bit プロセスは、同一プロセス内で混在できない」
が本ページ全体の核である。

  • 64bit の EXE は 64bit の DLL / COM しかロードできない
  • 32bit の EXE は 32bit の DLL / COM しかロードできない
  • 跨ぎたい場合はプロセスを分けるLocalServer32 の COM、
    別 EXE + IPC、WCF / 名前付きパイプ)。

「32bit の古い COM を使っているので、アプリ全体を 32bit のままにする」
という判断は、この制約から来る。

Webアプリケーション

IISのワーカプロセス(ASP や ASP.NETなどの
Web アプリケーションがホストされる)も 32bit(WOW64)を
サポートする。

補足(現在の設定箇所): IISでは
アプリケーション プールの詳細設定にある
「32 ビット アプリケーションの有効化」enable32BitAppOnWin64)で
切り替える。

  • True … そのプールの w3wp.exe が 32bit で起動する
  • False(既定)… 64bit で起動する

32bit の COMや ODBC ドライバに依存する古いアプリを
動かす際の定番設定である。
同一サーバ上で 32bit と 64bit のアプリを別プールにすれば共存できる
(IIS 6.0 ではできなかった)。

IIS Express を 64bit で動作させることも可能。

  1. Visual Studioのメニューから[ツール]-[オプション]を開く
  2. [プロジェクトおよびソリューション]-[Web プロジェクト]を開く
  3. [Web サイトおよびプロジェクト用 IIS Express の 64 ビットバージョンを使用]の
    チェックを ON にする

レガシーASP

なお、レガシー ASP は、32bit(WOW64)もサポートする。
ただし、殆どの場合は、使用する COMが「32bit の VB COM」で
開発されているので、WOW64上で 32bit アプリケーションとして
動作させることとなる。

データモデル

最も大きな問題は 32bit、64bit 間のデータモデルの変更である。

今日では、多くの 64bit コンパイラが LP64 モデルを採用している
(Solaris、AIX、macOS、z/OS のネイティブコンパイラなど)が、
マイクロソフトの VC++コンパイラは LLP64 モデル
採用している。

  • LP64 モデルの欠点
    long 型データを int 型変数に代入するときに
    オーバーフローが発生する可能性がある点である。

  • LLP64 モデルの欠点
    ポインタを long 型に cast できないため long long
    (VC++ コンパイラでは INT64__int64LONGLONG)を
    使用する必要がある点である。

64bit データモデル

データモデル short int long long long ポインタ 処理系
LLP64 16 32 32 64 64 Microsoft Win64 (x64/IA64)
LP64 16 32 64 64 64 ほとんどの Unix と Unix 風 OS (Solaris, Linux, etc.)
IP64 16 64 32 64 64 ?
ILP64 16 64 64 64 64 HAL
SILP64 64 64 64 64 64 ?

補足(これが移植の最大の落とし穴): Windows だけ long が 32bit
という点が、Linux/Unix との間でコードを行き来させる際の
最も大きな非互換である。

long p = (long)ptr;   /* Linux では通るが、Windows x64 では切り捨てられる */

移植性を確保するには、
ポインタを整数に入れるなら intptr_t / uintptr_t
サイズが要るなら size_t
明示的な幅なら int64_t を使う(<stdint.h>)。
Windows API では INT_PTR / LONG_PTR / DWORD_PTR
同じ役割を担う。

64bit COM

  • 必要に応じて 64bit 用 VC++コンパイラを追加インストール、
    構成マネージャから 64bit 用のプラットフォームを新規作成することで
    64bit COMを作成可能。
    ポインタを long 型に cast するようなコードが無ければ
    ストレート移行が可能である。

  • また、regsvr32 する際に、(恐らく PE ヘッダを参照することで、)
    自動的に「COM の生成情報」の登録先であるレジストリを標準(64bit 用)とするか、
    WOW64(32bit 用)とするかの切り替えが為される。
    そして、COM を生成するときは、呼出元プロセスが 64bit or 32bit によって
    参照先レジストリが切り替えられるため、
    適切な COM(64bit or 32bit)を生成することができる。

  • このため、ADODB などのミドルウェアも、64bit サポートがされていれば、
    64bit or 32bit(WOW64)の双方のプロセスから利用できる
    (余談:WSHWScript.exeCScript.exe
    64bit 用、32bit 用の双方が用意されている)。

  • また、.NET では Any CPU のコンパイルが可能なので、
    64bit・32bit を意識しないこともありますが、
    アンマネージコードと連携する場合は .NET の呼出元プロセスが
    64bit or 32bit のどちらで動作しているか注意が必要です。

移行メモ(正誤): 元ページの Regsrv32 は、
正しくは regsvr32 である(sv の順序)。

.NET、ASP.NET

以下、.NET のアプリケーションの 64bit 対応のポイントについて説明する。

100%タイプ セーフな場合

100%タイプ セーフなマネージ コードであれば、そのまま移行可能。

  • 100%タイプ セーフとは?
    • DLL(platform)呼び出し、COM呼び出しをしていないこと。
    • /clr:safe オプションでコンパイルされており、
      低レベルな処理の実行が許可されていないこと。
      • ポインタの宣言と処理
      • ポインタと整数型の変換
      • 変数のアドレス取得

100%タイプ セーフでない場合

100%タイプ セーフでない場合は、Windows の 64bit プラットフォームが
LLP64 モデルであることを意識してコードを書きなおす必要がある。

  • IntPtr.Size を使用してプラットフォームを識別可能。

  • ポインタを受け取る場合は、IntPtr 型を使用する。

  • Marshal クラスを用いてデータのマーシャリングを行う場合は、
    メモリの境界整列(アライメント)を考慮する必要がある。

    • LayoutKind.Sequential を使用する場合は StructLayoutAttribute.Pack
    • LayoutKind.Explicit を使用する場合は FieldOffsetAttribute
  • BinaryFormatter クラスを使用したバイナリ・シリアライズは、
    IntPtr を保存して 32bit ⇔ 64bit プロセス間を跨ぐ場合にのみ問題を起こす。

  • 32bit の COMは、tlbimp.exe を使用して 64bit 用の RCW を
    生成することで、WOW64でホストされる
    32bit アウトプロセスを呼び出し可能。

    • 64bit 用の RCW を生成する:
      tlbimp.exe foo.dll /machine:x64 /out:Interop.Foo.dll
    • 32bit の COM を登録する:regsvr32.exe foo.dll
    • コンパイル オプションを x64 に変更して RCW を参照設定。
  • C#のアンセーフコード、C++/CLI は
    問題が起こらないか見直しが必要になる。

移行メモ(正誤): 元ページのコマンド例は tlbim.exe
綴られスペースも欠けていたが、正しくは
tlbimp.exe foo.dll /machine:x64 /out:Interop.Foo.dll である。

補足(アウトプロセス COM の前提): 「32bit COM を 64bit プロセスから
呼べる」のは、その COM が LocalServer32(アウトプロセス)である場合
限られる。InprocServer32(DLL)の 32bit COM は、
どうやっても 64bit プロセスにロードできない
COMの項を参照)。

インプロセス COM を跨ぎたい場合は、COM+ アプリケーションとして
アウトプロセス化する
(サロゲート dllhost.exe を使う)という
迂回策がある。

コンパイル オプション(構成の target platform)

  • コンパイル オプション(構成の target platform)を Any CPU か、
    x64 に変更する。
  • .NET Framework 2.0 以降からのサポート。
    .NET Framework 1.0、1.1 は WOW64上で実行する。
  • アセンブリに指定されているコンパイル オプションを調査する方法
    ILDASM.exe の[表示]→[ヘッダー]で
    COFF Header の Machine Type を確認する。

既定値

  • VS2010:EXE を作るプロジェクトのデフォルトが Any CPU から x86 に変更。
    理由は、

    • アーキテクチャ中立の Any CPU EXE は通常、
      価値よりもトラブルのほうが多くコスト高。
    • 32bit はいずれにしろより速い傾向がある。
    • いくつかの機能が 64bit では利用できない。
  • VS2012 以降:再び、デフォルトは Any CPU に戻っている。

補足(現在の既定と "Prefer 32-bit"): 現在の
.NET Core 以降では、

種別 既定
dotnet CLI / SDK スタイル Any CPUPlatformTarget 未指定)
発行時(dotnet publish -r win-x64 RID で明示

となっており、実行時のビット数はどのランタイムで動かすかで決まる。

なお .NET Framework 時代の
「32 ビットを優先する(Prefer 32-bit)」 チェックは、
Any CPU なのに 32bit で動くという紛らわしい挙動を生む。
「Any CPU にしたのに 64bit にならない」という相談の多くは
これが原因なので、移行時には必ず確認したい
.NET Core 以降にはこの設定は無い)。

参考

WOW64

  • WOW64 - Wikipedia
    https://ja.wikipedia.org/wiki/WOW64

  • WOW64 のベスト プラクティス(要点)

    • ファイル システム リダイレクトはスレッド単位であるため、
      リダイレクトの無効化が必要なオペレーションは別スレッドに分離する。
    • タスクの実行後、できるだけ速やかにリダイレクトを再度有効化する。
    • 64bit プロセスを 32bit バージョンのプロセスと同時にインストールする場合は、
      相互運用性に注意する。
    • ソケット、パイプ、RPC、および COMといった
      プロセス間コミュニケーションを使用する場合は、
      データの処理におけるビット幅別の対応状況をチェックする。
    • 32bit プロセスから 64bit プロセスへのアクセスを避ける。
  • @IT:Win32アプリケーションを実行するWOW64
    http://www.atmarkit.co.jp/fwin2k/special/win64_02/win64_02_01.html

移行


Tags: 移行, プログラミング, .NET開発, Windows

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally