はじめに
窓の杜でこのような記事が出ていました。
今回の問題は「Large Address Aware 対応 32bit アプリケーションが Windows 10 / 11 環境 (WOW64) で実行されている時に CopyFile() に失敗する事がある」というものです。
Large Address Aware
Large Address Aware が有効な 32bit Windows では各ユーザープロセスに 2GB を超える仮想アドレス空間が割り当てられるようになり、WOW64 環境 (64bit Windows) では各ユーザープロセスに 4GB の仮想アドレス空間が割り当てられるようになります。
Windows | 仮想アドレス空間 |
---|---|
Large Address Aware が有効でない 32bit Windows | 2GB |
Large Address Aware が有効な 32bit Windows | < 3GB |
64bit Windows (WOW64) | 4GB |
ユーザープロセスに 2GB を超える仮想アドレス空間が割り当てられている場合、32bit アプリケーションの PE ヘッダフラグに IMAGE_FILE_LARGE_ADDRESS_AWARE 立っていると、2GB を超えるメモリを扱う事ができます。
アプリケーションを Large Address Aware 対応にしたいのであれば、Integer によるポインタ操作をしていない事が条件です。ポインタを Integer でキャストしている場合には正常動作しない可能性があります。
See also:
- 4 GB のチューニング: BCDEdit と Boot.ini (learn.microsoft.com)
- Windows で 3 GB スイッチを有効にする方法 (Autodesk)
- 4-Gigabyte Tuning (Wikipedia: en)
- 2 GB limit (Wikipedia: en)
- /LARGEADDRESSAWARE (大きいアドレスの処理) (learn.microsoft.com)
Delphi アプリケーションを Large Address Aware 対応にするには?
1.プロジェクトオプションで追加する
プロジェクトオプションの [PE ヘッダーの追加フラグを設定]
に値を指定します。IMAGE_FILE_LARGE_ADDRESS_AWARE は 0x0020 (32) です。
[PE ヘッダーの追加のオプションフラグを設定]
という似たような設定があるので間違えないように注意してください。
0 以外の値がセットされていたら or する必要があります。
See also:
2.コンパイラ指令 {$SetPEFlags} で追加する
コンパイラ指令 {$SetPEFlags}
で追加する事もできます。プロジェクトファイルに記述します。
uses
.., Winapi.Windows;
...
{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}
{$SetPEFlags}
コンパイラ指令は Delphi 7 以降で使えますが、定数が Winapi.Windows.pas
(または Windows.pas
) に定義されていない場合があります。その際には値 ($0020) で指定するか、以下の定義を行ってください。
IMAGE_FILE_LARGE_ADDRESS_AWARE = $0020;
{$SetPEFlags} は複数回記述できます。つまり、値を OR する必要はありません。
See also:
アプリケーションが Large Address Aware 対応かどうか調べるには?
dumpbin.exe? Delphi (や C++Builder) をインストールした環境なら、<インストールフォルダ>\bin
に TDUMP.EXE と GREP.EXE があるので、これらを使います。
tdump -e ファイル名 | grep "^Flags"
ファイル名
に調べたい実行ファイル (*.exe) を指定します。実行すると、次のような結果が得られます。
STDIN
Flags 122 [ executable linenumbers symbols largeaddr backwards 32bit ]
フラグに largeaddr
が含まれていれば Large Address Aware 対応アプリケーションです。
See also:
おわりに
今回の問題は「Large Address Aware 対応アプリケーションで CopyFile() に失敗する事があるよ!」というものでした。アプリケーションが Large Address Aware 対応でなかったり、64bit EXE なのであれば影響を受けません。
IMAGE_FILE_LARGE_ADDRESS_AWARE フラグはデフォルトで無効となっているので、特に問題になる事はないでしょう。
そういえば Delphi の IDE 自体は 10 Seattle 以降で Large Address Aware 対応になっているのですが、こちらの方は影響を受けなかったのでしょうか?
See also: