5

メモリ リークの問題をデバッグしようとしています。malloc/free/realloc トレースを取得するためにmtrace()を使用しています。プログラムを実行したところ、巨大なログ ファイルが作成されました。ここまでは順調ですね。しかし、ファイルの解釈に問題があります。次の行を見てください。

@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502570 0x68
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502620 0x30
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1501460 0xa64

これに関する奇妙な点は、1 つの呼び出し (同じ戻りアドレス) が 4 つの割り当てを担当していることです。

さらに見知らぬ人:

@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa2c
…
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80

これらの 2 行の間で、ブロック 0x2aaab43a1700 が解放されることはありません。

誰もこれを説明する方法を知っていますか? 1 回の呼び出しで 4 つの割り当てが発生するのはなぜですか? また、以前に割り当てられたアドレスを malloc で返すにはどうすればよいでしょうか。

edit 2008/09/30: GLIBC が提供する mtrace() 出力を分析するスクリプト (mtrace.pl) は、ここでは役に立ちません。それはただ言うでしょう:0x2aaab43a1700重複を割り当てます。しかし、どうしてこれが起こるのでしょうか?

4

4 に答える 4

8

mtrace の直接出力を見ていますが、これは非常に紛らわしく、直感に反しています。幸いなことに、この出力の解析に非常に簡単に役立つ perl スクリプト (mtrace と呼ばれ、glibc-utils 内にあります) があります。

デバッグをオンにしてビルドをコンパイルし、次のように mtrace を実行します。

$ gcc -g -o test test.c
$ MALLOC_TRACE=mtrace.out ./test
$ mtrace test mtrace.out

Memory not freed:
-----------------
   Address     Size     Caller
0x094d9378    0x400  at test.c:6

出力は消化しやすいはずです。

于 2008-09-30T18:50:17.670 に答える
5

メモリを割り当てている関数が複数回呼び出されています。呼び出し元のアドレスは、割り当てを行ったコードを指しており、そのコードは単に複数回実行されています。

C での例を次に示します。

void *allocate (void)
{
  return (malloc(1000));
}

int main()
{
  mtrace();
  allocate();
  allocate();
}

mtrace からの出力は次のとおりです。

メモリが解放されていません:
-----------------
           アドレス サイズ 発信者
0x0000000000601460 0x3e8 at 0x4004f6
0x4004f6 の 0x0000000000601850 0x3e8

発信者アドレスが同一であることに注意してください。これが、同じバグが複数回見られ、いくつかのメモリ リークが発生しているため、mtrace 分析スクリプトがそれらが同一であると言っている理由です。

デバッグ フラグ (-g) を指定してコンパイルすると、次のことができる場合に役立ちます。

メモリが解放されていません:
-----------------
           アドレス サイズ 発信者
0x0000000000601460 0x3e8 at /home/andrjohn/development/playground/test.c:6
0x0000000000601850 0x3e8 at /home/andrjohn/development/playground/test.c:6
于 2008-10-03T21:07:33.183 に答える
0

valgrind でアプリを実行してみてください。実際に何がリークされているかをよりよく理解できるかもしれません。

于 2008-09-30T17:10:55.897 に答える
0

One possible explanation is that the same function is allocating different buffer sizes? One such example is strdup.

For the second question, it is possible that the runtime is allocating some "static" scratch area which is not intended to be freed until the process is terminated. And at that point, the OS will clean-up after the process anyway.

Think about it this way: in Java, there are no destructors, and no guarantees that finalization will be ever called for any object.

于 2008-09-30T17:04:52.667 に答える