mtraceでメモリーリークを検出する方法
mtraceでメモリーリークを検出する方法を紹介します。
1.はじめに
次のプログラムを書きました。
#include <malloc.h>
int main() {
void *a, *b;
a = malloc(100);
b = malloc(100);
free(a);
free(b);
}
このプラグラムで次のように"free(a);"を書き忘れた場合、簡単にメモリーリークを検出したいのですが方法が分かりません。
int main() {
void *a, *b;
a = malloc(100);
b = malloc(100);
free(b);
}
ということで、mtraceを使ってメモリーリークを検出する方法を、順を追って紹介します。
2.プログラム修正
赤色の3行を追加します。
#include <malloc.h>
#include <mcheck.h>
int main() {
mtrace();
void *a, *b;
a = malloc(100);
b = malloc(100);
free(a);
free(b);
muntrace();
}
mtrace()は、malloc, realloc, freeのハンドラを組み込むシステムコールで、muntrace() はこれらのハンドラを解除するシステムコールです。
3.ビルド
"-g"オプションつきでビルドします。
% g++ -g test.cc
4.環境変数の設定
実行前にMALLOC_TRACEを設定します。MALLOC_TRACEは、mtrace() が出力するファイルを指定するための環境変数です。
% export MALLOC_TRACE="/tmp/mtrace.log"
5.実行
これでプログラムを実行します。
% ./a.out
6.実行ログの解析
実行ログの解析はmtraceコマンドで行います。コマンドオプションは次のとおりです。
% mtrace [プログラム名] [ログファイル名]
このmtraceコマンドでメモリーリークを検出できます(一部期待通りに動作していないようですが...)。
% mtrace ./a.out $MALLOC_TRACE
$* is no longer supported at /usr/bin/mtrace line 2.
Memory not freed:
-----------------
Address Size Caller
0x01481460 0x64 at ./a.out:[0x4006e7]
「Memory not freed:」の下に表示されているのが、リークしているメモリです。
実際には「Caller」の部分にファイルと行番号が出力されるようですが、リンク先の動的ライブラリがデバグ用のシンボル情報を取得できないため、期待通りに出力されていないようです。
ちなみにメモリリークがない場合、次のように「No memory leaks.」が表示されました。
% mtrace ./a.out $MALLOC_TRACE
$* is no longer supported at /usr/bin/mtrace line 2.
No memory leaks.
mtraceがインストールされていない場合はyumでインストールできるようです。
% yum install glibc-utils
yumが使えない環境であれば、rpmからインストールできます。今回は下記のページからRPMをダウンロードしてインストールしました。
RPM Other mtrace 2.1.3 i386 rpm
rpmコマンドは次の通りです。
% rpm -ivh mtrace-2.1.3-17.i386.rpm
準備しています... ################################# [100%]
更新中 / インストール中...
1:mtrace-2000102602:2.1.3-17 ################################# [100%]
ちなみに、実行ログは次のようになっているので、mtraceコマンドが使えなくても力技で解析は可能と思われます。
% cat /tmp/mtrace.log
= Start
@ ./a.out:[0x4006e7] + 0x1481460 0x64
@ ./a.out:[0x4006f5] + 0x14814d0 0x64
@ ./a.out:[0x400705] - 0x14814d0
= End
"+"がmalloc、"-"がfreeで、"0x1481460"や"0x14814d0"がアドレスですね。
7.参考サイト
参考サイトは下記です。ありがとうございました。