実行可能ファイルの1つは大量のメモリを使用するため、このフラグにリンクする必要があります。
しかし、なぜ1つのEXEファイルに特別な扱いをするのですか。標準化してみません/LARGEADDRESSAWARE
か?
/LARGEADDRESSAWARE
だから問題は、あなたがそれを必要としないとしても、使用することに何か問題がありますか?すべてのEXEファイルの標準として使用してみませんか?
実行可能ファイルの1つは大量のメモリを使用するため、このフラグにリンクする必要があります。
しかし、なぜ1つのEXEファイルに特別な扱いをするのですか。標準化してみません/LARGEADDRESSAWARE
か?
/LARGEADDRESSAWARE
だから問題は、あなたがそれを必要としないとしても、使用することに何か問題がありますか?すべてのEXEファイルの標準として使用してみませんか?
LargeAddressAware
32ビット実行可能ファイルにフラグを盲目的に適用すると、時限爆弾が展開されます。このフラグを設定することにより、OSに証言します。
はい、私のアプリケーション(および実行時にロードされるすべてのDLL)は、最大4GBのメモリアドレスに対応できます。
したがって、プロセスのVASを2 GBに制限せずに、全範囲(4 GB)のロックを解除してください。」
しかし、あなたは本当に保証できますか?
プロセスが使用する可能性のあるすべてのシステムDLL、Microsoft再配布可能ファイル、およびサードパーティモジュールに対して責任を負いますか?
通常、メモリ割り当ては仮想アドレスを下位から上位に返します。したがって、プロセスが大量のメモリを消費しない限り(または、仮想アドレス空間が非常に断片化されていない限り)、2GBの境界を超えるアドレスを使用することはありません。これは、上位アドレスに関連するバグを隠しています。
そのようなバグが存在する場合、それらを特定するのは困難です。それらは散発的に「遅かれ早かれ」現れるでしょう。それは時間の問題です。
幸いなことに、Windows OSには非常に便利なシステム全体のスイッチが組み込まれています
。テスト目的では、MEM_TOP_DOWNレジストリ設定を使用します。
これにより、すべてのメモリ割り当てが通常のボトムアップではなく、トップダウンになります。
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management]
"AllocationPreference"=dword:00100000
(これは16進数の0x100000です。もちろんWindowsを再起動する必要があります)
このスイッチを有効にすると、問題を「後で」ではなく「早く」特定できます。理想的には、「最初から」それらを見ることができます。
補足:最初の分析では、ツールVMmap
(SysInternals)を強くお勧めします。
AllocationPreference
LAAフラグを32ビット実行可能ファイルに適用する場合、TopDownスイッチが設定されたx64OSで完全にテストする必要があります。
独自のコードの問題については、修正できる場合があります。
非常に明白な例を1つ挙げると、メモリポインタに符号付き整数の代わりに符号なし整数を使用します。
サードパーティのモジュールで問題が発生した場合は、作成者にバグの修正を依頼する必要があります。これを行わない限り、実行可能ファイルからLargeAddressAwareフラグを削除することをお勧めします。
テストに関する注意:
MemTopDownレジストリスイッチは、それ自体がLAAが有効になっていない「テストランナー」によって実行される単体テストに対して望ましい結果を達成していません。
参照:x86LargeAddressAware互換性の単体テスト
PS:
また、非常に「関連性があり」、非常に興味深いのは、32ビットコードから64ビットへの移行です。
例については、以下を参照してください。
多くのレガシーコードは、「負の」ポインタが無効であることを期待して記述されているためです。32ビットプロセスの上位2Gbにあるものには、msbが設定されています。
そのため、Microsoftが安全にプレイするのははるかに簡単であり、(a)完全な4Gbを必要とし、(b)大容量メモリシナリオで開発およびテストされたアプリケーションでフラグを設定する必要があります。
お気づきのように、それほど難しいことではありません。
Raymond Chenは、彼のブログThe Old New Thingで、すべての(32ビット)アプリケーションでオンにする際の問題について説明しています。
いいえ、このコンテキスト(C / C ++)での「レガシーコード」は、ポインターのMSBで醜いトリックを実行するコードだけではありません。
また、正しい型を使用する代わりに、「int」を使用して2つのポインタの差、つまりメモリ領域の長さを格納するすべてのコードが含まれます。「size_t」:「int」は31ビットであり、処理できません。 2Gbを超える値。
コードの大部分を修正する方法は、コードを調べて、無害な「署名付きと署名なしの混合」警告をすべて修正することです。少なくとも、int型の引数が実際にはメモリの長さである関数を定義していない場合は、この作業の大部分を実行する必要があります。
ただし、その「レガシーコード」は、何も修正しなくても、おそらくかなり長い間正しく機能するようです。
1つのブロックに2Gbを超える容量を割り当てる場合にのみ、中断します。または、互いに2Gb以上離れている2つの無関係なポインターを比較する場合。
関係のないポインタを比較することは、技術的には未定義の動作であるため、それを実行するコードはそれほど多くありません(ただし、確信は持てません)。
また、合計で2Gbを超える必要がある場合でも、実際には、プログラムがそれよりも大きい単一の割り当てを行うことはありません。実際、Windowsでは、LARGEADDRESSAWAREを使用しても、メモリの編成方法を考えると、デフォルトではそれほど多くを割り当てることはできません。2Gbを超える連続ブロックを取得するには、システムDLLをシャッフルする必要があります
しかし、マーフィーの法則によれば、ある種のコードはいつか壊れてしまいます。チェックせずにLARGEADDRESSAWAREを有効にした後、これが行われたことを誰も覚えていない場合は、非常に長い間発生します。