C言語,mtrace()を使用してメモリリークを検出(確認)する

スポンサーリンク

鍛錬 400

C言語,mtrace() を使用してメモリリークを検出(確認)する

プログラムのメモリリークを検出する方法の一つとして、mtrace() と muntrace() を使用する方法があります。

mtrace() について

mtrace() については、以下に示す通りです。

#include <mcheck.h>

void mtrace(void);
 

 
mtrace() は、malloc()、realloc()、free() 等、メモリ割り当て関数のフック関数を組み込み、メモリ割り当てと割り当て解除の追跡情報を記録します。

追跡情報を利用して、メモリリークを検出することができます。

muntrace() について

muntrace() については、以下に示す通りです。

#include <mcheck.h>

void muntrace(void);
 

 
muntrace() は、mtrace() によって組み込まれたフック関数を無効にし、メモリ割り当て関数の追跡情報を記録しないようにします。

フック関数が mtrace() によって正常に組み込まれなかった場合、muntrace() は機能しません。

スポンサーリンク

全体の流れ

以下は、mtrace() でメモリリークを確認する際の大まかな流れです。

  1. gcc にオプションの -g を付加してコンパイルする。
  2. 環境変数 MALLOC_TRACE に、ログが書き込まれるファイル名を設定する。
  3. プログラムを実行する。
  4. ログや解析結果を確認する。
スポンサーリンク

メモリリークしない場合の、mtrace() の挙動を確認

まずは、メモリリークしない場合の、mtrace() の挙動について確認します。

プログラム(メモリリークしない場合)

以下は、malloc() でメモリを割り当てた後、free() でメモリを開放してメモリリークをさせないプログラム、test_mtrace.c です。

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

// main
int main(void)
{
	char *p;
	
	// 追跡開始
	mtrace();
	
	// メモリ割り当て
	p = (char *)malloc(256);
	
	// メモリ解放
	free(p);
	
	// 追跡終了
	muntrace();
	
	return 0;
}

実行結果

以下は、次の順序でメモリリークの有無を確認しています。

  1. gcc にオプションの -g を付加してコンパイル
  2. 環境変数 MALLOC_TRACE を確認
  3. 環境変数 MALLOC_TRACE にログファイル名を設定
  4. 環境変数 MALLOC_TRACE を確認
  5. プログラム test_mtrace.c を実行
  6. ログを確認
  7. 解析結果を確認
[***@centos c]$ 
[***@centos c]$ gcc -g test_mtrace.c -o test_mtrace
[***@centos c]$ export -p | grep MALLOC_TRACE
[***@centos c]$ export MALLOC_TRACE=./test_mtrace.log
[***@centos c]$ export -p | grep MALLOC_TRACE
declare -x MALLOC_TRACE="./test_mtrace.log"
[***@centos c]$ ./test_mtrace
[***@centos c]$ cat test_mtrace.log
= Start
@ ./test_mtrace:[0x400614] + 0x203d460 0x100
@ ./test_mtrace:[0x400624] - 0x203d460
= End
[***@centos c]$ mtrace ./test_mtrace ./test_mtrace.log
No memory leaks.

 
上記に示した通り、結果は「No memory leaks.」となり、メモリリークしていないことが確認できました。

スポンサーリンク

メモリリークする場合の、mtrace() の挙動を確認

次に、メモリリークする場合の、mtrace() の挙動について確認します。

プログラム(メモリリークする場合)

以下は、malloc() でメモリを割り当てた後、free() でメモリを開放せずにメモリリークをさせているプログラム、test_mtrace.c です。

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

// main
int main(void)
{
	char *p;
	
	// 追跡開始
	mtrace();
	
	// メモリ割り当て
	p = (char *)malloc(256);
	
	// メモリ解放(今回はあえてリークさせるためコメントアウト)
//	free(p);
	(void)p;
	
	// 追跡終了
	muntrace();
	
	return 0;
}

実行結果

以下は、次の順序でメモリリークの有無を確認しています。

  1. gcc にオプションの -g を付加してコンパイル
  2. 環境変数 MALLOC_TRACE を確認
  3. 環境変数 MALLOC_TRACE にログファイル名を設定
  4. 環境変数 MALLOC_TRACE を確認
  5. プログラム test_mtrace.c を実行
  6. ログを確認
  7. 解析結果を確認
[***@centos c]$ gcc -g test_mtrace.c -o test_mtrace
[***@centos c]$ export -p | grep MALLOC_TRACE
[***@centos c]$ export MALLOC_TRACE=./test_mtrace.log
[***@centos c]$ export -p | grep MALLOC_TRACE
declare -x MALLOC_TRACE="./test_mtrace.log"
[***@centos c]$ ./test_mtrace
[***@centos c]$ cat test_mtrace.log
= Start
@ ./test_mtrace:[0x4005c4] + 0x23a5460 0x100
= End
[***@centos c]$ mtrace ./test_mtrace ./test_mtrace.log

Memory not freed:
-----------------
           Address     Size     Caller
0x00000000023a5460    0x100  at /home/***/***/test/c/test_mtrace.c:15

 
上記に示した通り、結果は「Memory not freed」となり、free() を実行していないためにメモリリークをしていることが分かりました。

Caller の項目に表示されている結果から、test_mtrace.c の 15 行目でメモリ領域を割り当てた後、free() をしていないことが分かりました。

タイトルとURLをコピーしました