メモリ解放漏れ・メモリ二重解放は組込みエンジニアにとって、背筋が凍る単語だ。
それは、即、残業しなさいという意味に転じる。
そこから、泥沼のデバッグにハマることがよくある。
そんな課題をスマートに解決するために、メモリ解放漏れやメモリ二重解放を検出するツール調べてみたので、メモメモ。
オープンソース CppCheckのインストールをしよう
Cppcheckを使うことでメモリ解放漏れを静的解析で見つけることが可能だ。CppCheckはその他にも、アロケーション(確保と解放)の不一致(メモリ二重解放),バッファオーバーランの検出ができる。OSSなので、誰でも無料で利用可能。
Cppcheckの使い方の日本語訳は、以下のサイトで公開されている。
(ものすごく感謝!)今回はこれを参考に自分でも試してみる。
Cppcheckでメモリリークを検出する
Cppcheckを利用するには、-enable=allオプションをつけて以下のコマンド実行。
cppcheck -enable=all [フアイル名]
試しにこんなコードを書いてみた。
memory_leak.c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int *p = NULL;
printf("*p = %x\n",p);
p = malloc(10);
printf("*p = %x\n",p);
return 0;
}
なかなか、喧嘩を売っているコードだけれども、
これをCppCheckでチェックすると、案の定怒られる。(よしよし (^-^))
$ cppcheck -enable=all memory_leak.c
Checking memory_leak.c
[memory_leak.c:12]: (error) Memory leak: p
Checking usage of global functions..
自分で定義したメモリ獲得/解放関数のメモリリークをチェックする
次に、ユーザ定義したメモリ獲得/解放関数をチェックする。
普通、C標準のメモリ獲得/解放関数を直接使用することはなく、自前の関数でカスタマイズして使用することが多い。メモリアロケート関数を別ファイルで宣言してみる。
hoge_memory.c
#include "hoge_memory.h"
void *hoge_malloc(void)
{
return malloc(10);
}
memory_leak.c
void hoge_free(void *p)
{
free(p);
}
#include <stdio.h>
#include "hoge_memory.h"
int main(void)
{
char *p = NULL;
printf("*p = %x\n",p);
p = (char *)hoge_malloc();
printf("*p = %x\n",p);
return 0;
}
$ cppcheck -enable=all memory\_leak.c hoge\_memory.c
Checking hoge_memory.c
1/2 files checked 40% done
Checking memory_leak.c
2/2 files checked 100% done
Checking usage of global functions..
Oh! 検出してくれないYo!!(゜д゜)/
こんなときは、-appendオプションを使用する。
使い方は、
cppcheck --append=<メモリ獲得・解放関数定義file> <静的解析対象file>
$ cppcheck -enable=all -append=hoge\_memory.c memory\_leak.c
Checking memory_leak.c
[memory_leak.c:13]: (error) Memory leak: p
Checking usage of global functions..
これで、、メモリリークを検出しました。
メモリ二重解放を検出する
おまけ。メモリ二重解放もこのとおり発見できます!スゲー。
int main(void)
{
char *p = NULL;
printf("*p = %x\n",p);
p = (char *)hoge_malloc();
printf("*p = %x\n",p);
hoge_free(p);
hoge_free(p);
return 0;
}
$ cppcheck -append=hoge\_memory.c memory\_leak.c
Checking memory_leak.c
[memory_leak.c:15]: (error) Deallocating a deallocated pointer: p
使われていない関数宣言
$ cppcheck -append=hoge\_memory.c -enable=all memory\_leak.c
Checking memory_leak.c
Checking usage of global functions..
[memory\_leak.c:18]: (style) The function 'hogehoge\_special' is never used