5

.NET アプリのメモリ リークを追跡しようとしています。Windows タスク マネージャーはメモリ使用量が一定のままであると報告しますが、Process Explorerはメモリ使用量が増加していると報告します。

タスク マネージャーで、唯一のメモリ列「メモリ (プライベート ワーキング セット)」を見ています。Process Explorer では、「Private bytes」列を調べています。これは、値が上がっていて、「Working set」の下の値がそうではないためです。

何回か割り当てた後、アプリがメモリ不足の例外でクラッシュするためです。問題は、タスク マネージャーがアプリのメモリ使用量を誤って報告するのはなぜですか? それだけでなく、グローバル システムの空きメモリも誤って報告します ([パフォーマンス] タブのグラフは一定のままです)。

私のコードは必要ないはずですが、完全を期すためにここにあります。大きな配列を保持する空のウィンドウが表示されます。いずれかのキーが押されると、ウィンドウが閉じられ、新しいアレイが保持された新しいウィンドウが開かれます。おそらくqt4dotnet GUIライブラリのバグが原因で、古いウィンドウがリークしました。

using System;
using com.trolltech.qt.gui;

namespace LeakTest
{
    class Test : QWidget
    {
        public byte[] Data = new byte[1000 * 1000 * 100];

        public Test()
        {
            show();
            GC.Collect(); // so measurements are more accurate
        }

        protected override void keyPressEvent(QKeyEvent arg__1)
        {
            disposeLater();
            new Test();
        }

        [STAThread]
        static void Main(string[] args)
        {
            QApplication.initialize(args);

            new Test();

            QApplication.exec();
        }
    }
}

OS: Windows7

興味深いことに、「データ」を次元の 2D ギザギザ配列にすると[1000 * 1000 * 100][1]、タスク マネージャーメモリ使用量の増加を報告します。

4

2 に答える 2

8

それらは2つの完全に異なる記憶手段です。ワーキングセットは、プログラムが使用するRAMの量です。これは常に変化する数値であり、他のプロセスが必要とするRAMの量に影響されます。RAMを使い果たすことはできません。Windowsは、マップされたページをページングファイルにスワップアウトすることにより、RAMを利用できるようにします。

プライベートバイトは、プログラムが使用する仮想メモリの量であり、他のプロセスとは共有されません。32ビットマシンでは、2ギガバイトの仮想メモリを使用できます。コードとデータの間で共有する必要があります。アドレス可能な量の仮想メモリに、要求された割り当てに対応するのに十分なスペースが残っていない場合に、OOMを取得します。はい、それはより正確な数値です。

一度に100メガバイトを要求するのは危険です。仮想メモリ空​​間は断片化する可能性があり、しばらくすると、まだ多くの空き仮想メモリが存在する可能性がありますが、100メガバイトを収容するのに十分な大きさの穴はありません。ジャグ配列は配列の配列であるため、この問題を解決します。必要なチャンクははるかに小さいため、残っている穴に簡単に合わせることができます。

64ビットオペレーティングシステムは、この問題を完全に解決します。プログラムにはギガバイトのアドレス空間がありますが、実際にはページングファイルの最大サイズによってのみ制限されます。あなたは単に大きな穴を使い果たすことはできません。

于 2011-02-04T20:14:46.037 に答える
1

メモリリークを追跡したいが、コードを読んでもそれを見つけることができない場合は、おそらくその仕事のために設計された実際のツールが必要です。

TaskManagerもProcessExplorerも、メモリリークをデバッグするための適切なツールではありません。返されていないメモリをどこに割り当てるかを教えてくれるものが必要です。

于 2011-02-04T20:25:05.373 に答える