8

私のアプリケーションは、その作業を実行するために大量のメモリと大きなデータ構造を必要とします。多くの場合、アプリケーションは 1 GB を超えるメモリを必要とし、場合によっては、顧客が数ギガバイトのメモリを持っているため、実際には 64 ビット バージョンのアプリケーションを使用する必要があります。

以前は、メモリが 1.6 ~ 1.7 GB のメモリ使用量に達した場合、それは「メモリ不足」または「メモリ不足」に非常に近い状況であり、メモリを削減する必要があることをユーザーに簡単に説明できました。または 64 ビット版に移行してください。

昨年、アプリケーションがメモリ不足になる前に約 1 GB しか使用しないことが多いことに気付きました。いくつかの調査の結果、この問題の原因はメモリの断片化であると思われました。VMMAP (SysInternals ユーティリティ) を使用してアプリケーションのメモリ使用量を調べたところ、次のような結果が得られました。 アドレス空間の断片化

オレンジ色の領域は、アプリケーションによって割り当てられたメモリです。紫色の領域は実行コードです。

画像の下半分でわかるように、紫色の領域 (DLL の部分) がさまざまなアドレスにロードされているため、メモリが断片化されています。私の顧客が大量のデータを持っていない場合、これは実際には問題ではありませんが、私の顧客が 1 GB を超えるデータ セットを持っていて、アプリケーションの一部が大きなメモリ ブロック (50 MB など) を必要とする場合、メモリの割り当てに失敗し、アプリケーションがクラッシュする可能性があります。

私のデータ構造のほとんどは STL ベースであり、連続したメモリの大きなチャンクを必要としないことがよくありますが、場合によっては (非常に大きな文字列など)、メモリの連続したブロックが本当に必要になります。残念ながら、このような連続したメモリ ブロックを必要としないようにコードを変更できるとは限りません。

質問は次のとおりです。

  • 顧客のコンピューター上のすべての DLL に対して明示的に REBASE を使用せずに、またはすべての DLL を明示的にロードせずに、DLL がメモリにロードされる場所に影響を与えるにはどうすればよいでしょうか。
  • 独自のアプリケーション マニフェスト ファイルで DLL のロード アドレスを指定する方法はありますか?
  • または、(マニフェスト ファイルを介して) Windows に DLL を分散させないように指示する方法はありますか (この分散は ASLR と呼ばれていると思います)。

もちろん、Windows による DLL の自動/動的ロードに依存しているため、アプリケーションのマニフェスト ファイル内から影響を与えることができるソリューションが最適です。

私のアプリケーションは混合モード (マネージド + アンマネージド) アプリケーションですが、アプリケーションの大部分はアンマネージドです。

誰の提案ですか?

4

3 に答える 3

5

まず、仮想アドレス空間の断片化が必ずしもメモリ不足の原因になるとは限りません。これは、アプリケーションが適切なサイズの連続したメモリ ブロックを割り当てる必要がある場合に当てはまります。それ以外の場合、断片化の影響は小さいはずです。

ほとんどのデータは「STLベース」であると言いますが、たとえば巨大なものを割り当てるstd::vectorと、連続したメモリブロックが必要になります。

私の知る限り、ロード時にDLLの優先マッピングアドレスを指定する方法はありません。そのため、オプションは 2 つしかありません。それをリベースするか (DLL ファイル)、自分で DLL をロードするように実装するか (もちろん簡単なことではありません)。

通常、標準の Windows API DLL をリベースする必要はありません。それらはアドレス空間に非常に緊密にロードされます。一部のサードパーティ DLL (Windows フック、ウイルス対策インジェクションなど) から断片化が発生する場合があります。

于 2011-11-17T16:37:08.743 に答える
3

マニフェストでこれを行うことはできません。リンカーの /BASE オプションで行う必要があります。リンカ + 詳細 + IDE のベース アドレス。最も柔軟な方法は、/BASE:@filename,key 構文を使用して、リンカがテキスト ファイルからベース アドレスを読み取るようにすることです。

テキスト ファイルを埋める最良の方法は、[デバッグ] + [ウィンドウ] + [モジュール] ウィンドウからです。デバッガーにロードされたプログラムのリリース ビルドを取得し、シバン全体をロードします。Debug + Break All、ウィンドウを表示し、テキスト ファイルにコピー アンド ペーストします。必要な形式に合わせて編集し、[アドレス] 列からロード アドレスを計算します。テキスト ファイルを常に調整しなくて済むように、DLL 間には十分なスペースを空けてください。

于 2011-11-17T18:39:44.443 に答える