freeし忘れた領域を教えてくれるmtrace

mtraceについてのメモ。

何ができるのか

mallocして、freeし忘れたと思われる領域をピックアップしてくれる。 ただし、GNU拡張機能なので、どこの環境でも使えるわけではない。

どうやるのか

3行のソース修正、デバッグオプションビルド、トレースしながら実行、解析

の順に行う。

1. ソース修正

下記三行を追加する。

  • mcheck.hをinclude。
  • トレース開始地点にmtrace();
  • トレース終了地点にmuntrace();

2. ビルド

-g オプションを付けてデバッグビルドするだけ。

$ gcc -g test.c

3. 実行

MALLOC_TRACE環境変数で、トレース結果の出力先を指定してから実行する。

$ MALLOC_TRACE=output.txt ./a.out

4. 解析

mtraceコマンドにトレース結果ファイルとトレース対象のバイナリを引数として与えて解析する。 mtraceコマンドは、CentOSの場合は、glibc-utilsに含まれている。

free忘れと思われるアドレス、サイズ、呼び元が出力される。 よそのライブラリ内部など、デバッグビルドしていない箇所が呼び元の場合、実行アドレスのみの表示になるようだ。

$ mtrace a.out output.txt

サンプル

下記サンプルコードでお試し。

#include <stdlib.h>
#include <mcheck.h>

int main(void){
  int i;
  char* p_str = NULL;

  mtrace();

  for(i=0; i<10; i++){
    p_str = (char*)malloc(sizeof(char)*4);/* LEAK */
  }

  muntrace();
  return 0;
}

これを-gオプションを付けてコンパイル

$ gcc -g test.c

トレース結果の出力先を指定して実行。

$ MALLOC_TRACE=./trace.txt ./a.out

mtraceコマンドで出力結果を解析。

下記のようにアドレス、サイズ、呼び元が出力される。

$ mtrace a.out trace.txt 

Memory not freed:
-----------------
           Address     Size     Caller
0x00000000020d4460      0x4  at /home/.../mtrace_test/test.c:11
0x00000000020d4480      0x4  at /home/.../mtrace_test/test.c:11
0x00000000020d44a0      0x4  at /home/.../mtrace_test/test.c:11
0x00000000020d44c0      0x4  at /home/.../mtrace_test/test.c:11
0x00000000020d44e0      0x4  at /home/.../mtrace_test/test.c:11
0x00000000020d4500      0x4  at /home/.../mtrace_test/test.c:11
0x00000000020d4520      0x4  at /home/.../mtrace_test/test.c:11
0x00000000020d4540      0x4  at /home/.../mtrace_test/test.c:11
0x00000000020d4560      0x4  at /home/.../mtrace_test/test.c:11
0x00000000020d4580      0x4  at /home/.../mtrace_test/test.c:11
$