mtraceでメモリーリークを検出する方法

mtraceでメモリーリークを検出する方法

Posted at October 4,2017 12:03 AM
Tag:[C/C++]

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.参考サイト

参考サイトは下記です。ありがとうございました。

関連記事
トラックバックURL


コメントする
greeting

*必須

*必須(非表示)


ご質問のコメントの回答については、内容あるいは多忙の場合、1週間以上かかる場合があります。また、すべてのご質問にはお答えできない可能性があります。予めご了承ください。

太字イタリックアンダーラインハイパーリンク引用
[サインインしない場合はここにCAPTCHAを表示します]

コメント投稿後にScript Errorや500エラーが表示された場合は、すぐに再送信せず、ブラウザの「戻る」ボタンで一旦エントリーのページに戻り(プレビュー画面で投稿した場合は、投稿内容をマウスコピーしてからエントリーのページに戻り)、ブラウザをリロードして投稿コメントが反映されていることを確認してください。

コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。例えば「<$MTBlogURL$>」は「&lt;$MTBlogURL$&gt;」となります(全て半角文字)