6

メモリ リークを解決しようとしている C++ アプリケーションがあり、仮想メモリと物理メモリの違いを完全には理解していないことに気付きました。

結果top(16.8g = 仮想、111m = 物理):

4406 um 20 0 16.8g 111m 4928 S 64.7 22.8 36:53.65 client

私のプロセスは、ユーザーごとに 1 つずつ、500 の接続を保持します。これらの数では、ユーザーごとに約 30 MB の仮想オーバーヘッドがあることを意味します。私のアプリケーションの詳細には立ち入らずに、仮想メモリが実際に何を意味するのかを理解していない場合、すべてのベクトル、構造体、スレッド、スタック上の関数などを追加して、これがリモートで現実的に聞こえる唯一の方法です。-O 最適化フラグはありません。

だから私の質問は:

  • C++ のどの操作が仮想メモリをそれほど膨張させるのでしょうか?
  • タスクが大量の仮想メモリを使用している場合、問題はありますか?
  • スタックおよびヒープ関数の変数、ベクトルなど - これらは必然的に物理メモリの使用を増加させますか?
  • delete(またはそのような方法で)メモリ リークを削除すると、free()必然的に物理メモリと仮想メモリの両方の使用量が削減されますか?
4

3 に答える 3

13

仮想メモリは、プログラムが扱うものです。mallocこれは、、、その他によって返されたすべてのアドレスで構成されますnew。各プロセスには、独自の仮想アドレス空間があります。仮想アドレスの使用は、理論的にはプログラムのアドレス サイズによって制限されます。32 ビット プログラムには 4GB のアドレス空間があります。64 ビット プログラムには、はるかに多くの機能があります。実際には、プロセスが割り当てることができる仮想メモリの量は、これらの制限よりも少なくなります。

物理メモリは、マザーボードにはんだ付けされているか、メモリ スロットに取り付けられているチップです。任意の時点で使用される物理メモリの量は、コンピューターの物理メモリの量に制限されます。

仮想メモリ サブシステムは、プログラムが使用する仮想アドレスを、CPU が RAM チップに送信する物理アドレスにマップします。特定の時点で、割り当てられた仮想アドレスのほとんどはマップされていません。したがって、物理メモリの使用量は仮想メモリの使用量よりも少なくなります。割り当てられているがマップされていない仮想アドレスにアクセスすると、オペレーティング システムは目に見えない形で物理メモリを割り当ててマップします。仮想アドレスにアクセスしないと、オペレーティング システムは物理メモリのマップを解除する場合があります。

あなたの質問に順番に答えるには:

  • C++ のどの操作が仮想メモリをそれほど膨張させるのでしょうか?

newmalloc、大きな配列の静的割り当て。通常、プログラムでメモリを必要とするもの。

  • タスクが大量の仮想メモリを使用している場合、問題はありますか?

プログラムの使用パターンによって異なります。一度も触れたことのない大量のメモリ トラックを割り当てる場合、およびプログラムが 64 ビット プログラムである場合、仮想メモリのギグを使用しても問題ない可能性があります。

また、メモリ使用量が際限なく増加すると、最終的にリソースが不足します。

  • スタックおよびヒープ関数の変数、ベクトルなど - これらは必然的に物理メモリの使用を増加させますか?

必ずしもそうではありませんが、可能性があります。変数に触れるという行為は、少なくとも瞬間的に、それ (およびそれに「近い」すべてのメモリ) が物理メモリにあることを保証します。(余談: のようなコンテナstd::vectorはスタックまたはヒープに割り当てられますが、含まれるオブジェクトはヒープに割り当てられます。)

  • (delete または free() などを介して) メモリ リークを削除すると、必然的に物理メモリと仮想メモリの両方の使用量が削減されますか?

体格:たぶん。仮想: はい。

于 2012-06-05T16:37:10.370 に答える
3

仮想メモリは、プロセスによって使用されるアドレス空間です。各プロセスは、ポインターの 64 ビット (アーキテクチャによっては 32 ビット) のアドレス指定可能なバイトの完全なビューを持っていますが、すべてのバイトが実際のものにマップされるわけではありません。オペレーティングシステムは、仮想アドレスを実際の物理メモリページにマップするテーブルを管理します-またはそのアドレスが実際に何であれ(アプリケーションのメモリであるように見えても)。たとえば、アプリケーションのアドレスが何らかの関数を指している可能性がありますが、実際にはまだディスクからロードされておらず、それを呼び出すとページ フォールト割り込みが生成され、カーネルは適切なセクションを実行可能ファイルをアプリケーションのアドレス空間にマッピングして、実行できるようにします。

Linuxの観点から(そして私はほとんどの最新のOSを信じています):

  • メモリを割り当てると、仮想メモリが膨張します。割り当てられたメモリを実際に使用すると、物理メモリの使用量が増加します。やりすぎるとディスクにスワップされ、最終的にプロセスが強制終了されます。
  • mmap.ing ファイルは、仮想メモリの使用量のみを増加させます。これには、実行可能ファイルのサイズが含まれます。実行可能ファイルが大きいほど、より多くの仮想メモリが使用されます。
  • 仮想メモリを使い果たす唯一の問題は、仮想メモリが枯渇する可能性があることです。これは主に、4 GB しかない 32 ビット システムの問題です (1 GB はカーネル用に予約されているため、アプリケーション データには 3 GB しかありません)。
  • スタックに変数を割り当てる関数呼び出しは、物理メモリの使用量を増やす可能性がありますが、(通常) このメモリをリークすることはありません。
  • 割り当てられたヒープ変数は仮想メモリを占有しますが、実際に物理メモリを取得できるのは、それらを読み書きする場合のみです。
  • 変数を解放または削除しても、必ずしも仮想/物理メモリの消費が削減されるとは限りません。アロケータの内部に依存しますが、通常は削減されます。
于 2012-06-05T16:50:50.740 に答える