web-dev-qa-db-ja.com

実行中のプロセスのメモリリークを見つけるにはどうすればよいですか?

実行中のプロセスのメモリリークを見つける方法はありますか? Valgrindを使用して、プロセスの開始前にメモリリークを見つけることができます。 GDBを使用して、実行中のプロセスにアタッチできます。実行中のプロセスのメモリリークをデバッグするにはどうすればよいですか?

23

だれがメモリをリークしているのかを見つけるためのほぼ保証された手順を次に示します。

  1. メモリリークの原因となっているプロセスのPIDを調べます。

    ps -aux
    
  2. /proc/PID/smapsをキャプチャし、BeforeMemInc.txtなどのファイルに保存します。

  3. メモリが増加するまで待ちます。
  4. 再度キャプチャ/proc/PID/smapsして保存afterMemInc.txt
  5. 最初のsmapsと2番目のsmapsの違いを見つけます。 g。と

    diff -u beforeMemInc.txt afterMemInc.txt

  6. メモリが増加したアドレス範囲を書き留めます。次に例を示します。

       beforeMemInc.txt            afterMemInc.txt
    ---------------------------------------------------
    2b3289290000-2b3289343000   2b3289290000-2b3289343000  #ADDRESS
    Shared_Clean:    0 kB       Shared_Clean:    0 kB          
    Shared_Dirty:    0 kB       Shared_Dirty:    0 kB
    Private_Clean:   0 kB       Private_Clean:   0 kB
    Private_Dirty:  28 kB       Private_Dirty:  36 kB  
    Referenced:     28 kB       Referenced:     36 kB
    Anonymous:      28 kB       Anonymous:      36 kB  #INCREASE MEM
    AnonHugePages:   0 kB       AnonHugePages:   0 kB
    Swap:            0 kB       Swap:            0 kB
    KernelPageSize:  4 kB       KernelPageSize:  4 kB
    MMUPageSize:     4 kB       MMUPageSize:     4 kB
    Locked:          0 kB       Locked:          0 kB
    VmFlags: rd wr mr mw me ac  VmFlags: rd wr mr mw me ac
    
  7. gDBを使用して実行中のプロセスでメモリをダンプするか、gcore -o processを使用してコアダンプを取得します

  8. 実行中のプロセスでgdbを使用して、メモリをいくつかのファイルにダンプしました。

    gdb -p PID
    dump memory ./dump_outputfile.dump 0x2b3289290000 0x2b3289343000
    
  9. ここで、stringsコマンドまたはhexdump -Cを使用してdump_outputfile.dumpを出力します

    strings outputfile.dump
    
  10. これらの文字列をソースコードに配置できる、読み取り可能なフォームが表示されます。

  11. ソースを分析してリークを見つけます。

13

memleax はあなたが望むものとまったく同じだと思います。

プログラムを再コンパイルしたり、ターゲットプロセスを再起動したりすることなく、実行中のプロセスのメモリリークをアタッチしてデバッグします。それは非常に便利で、生産環境に適しています。

GNU/LinuxとFreeBSDで動作します。

注:私は作者です。どんな提案でも歓迎します

==編集==

別のツール libleak を作成します。これは、LD_PRELOADによってメモリ関数をフックします。

また、ターゲットプログラムを変更する必要もありません。 LD_PRELOADで進行状況を再開する必要がありますが、実行中に検出を有効/無効にすることができます。

信号トラップがないため、パフォーマンスへの影響ははるかに少なくなります。

同様のツール(mtraceなど)と比較すると、疑わしいメモリリークポイントで完全なコールスタックが出力されます。

13
Bingzheng Wu

Linuxでは、プログラムで mtrace を有効にすることができますが、これはコードの変更です。

OpenBSDでは、 malloc stats を試すことができます。

Googleの リークチェッカー も一見の価値があるかもしれません。mtraceとは異なり、LD_PRELOAD再コンパイルを回避します。

6
Useless

プログラムがソースコードで直接起動した後の割り当て監視のサポートを提供しなければ、あなたは運が悪いと思います。私が考えることができる2つの理由はここにあります:

  • ヒープチェッカーは、プログラムの開始時に初期化されます。正確なタイミングを微調整する機能を提供するものもありますが、プログラムを実行するときにそれらを開始する環境変数を設定する必要があります。これは、各割り当てに対応する割り当て解除があることを確認するために監視し、それ以外の場合はいくつかを見逃してしまうためです。
  • ヒープチェックでは、通常、オペレーティングシステムによって提供される昇格された特権またはフックが必要です。プログラムの開始時にこれらのフックが提供されていない場合、ヒープチェッカーはそれらを利用できません。問題のプログラムの開始後、OSがこれらの特権を提供するとは思わない。

ただし、プログラムが仮想マシン内で実行されている場合、その環境は割り当ての監視をサポートしている可能性があります。私は知っていますJavaには、実行中のプログラムまたはVMに接続するいくつかの割り当ておよびガベージコレクション監視ツール( visualVM など)があります。

0
Chris Betti

IBMの Purify は、おそらく最も古く、最も洗練されたツールです。メモリリークの原因となるコードの行番号にフラグを立てます。

0
lifebalance