CppCheckでC言語/C++のメモリリーク(解放漏れ)を静的解析で検出する。

メモリ解放漏れ・メモリ二重解放は組込みエンジニアにとって、背筋が凍る単語だ。

それは、即、残業しなさいという意味に転じる。

そこから、泥沼のデバッグにハマることがよくある。

そんな課題をスマートに解決するために、メモリ解放漏れやメモリ二重解放を検出するツール調べてみたので、メモメモ。

オープンソース CppCheckのインストールをしよう

Cppcheckを使うことでメモリ解放漏れを静的解析で見つけることが可能だ。CppCheckはその他にも、アロケーション(確保と解放)の不一致(メモリ二重解放),バッファオーバーランの検出ができる。OSSなので、誰でも無料で利用可能。

CppCheckのダウンロードはココから

Cppcheckの使い方の日本語訳は、以下のサイトで公開されている。

(ものすごく感謝!)今回はこれを参考に自分でも試してみる。

cppcheck 日本語マニュアル – 一人ぼっちの共鳴

cppcheck 英語マニュアルはこちちから

Cppcheckでメモリリークを検出する

Cppcheckを利用するには、–enable=allオプションをつけて以下のコマンド実行。

[text]

cppcheck –enable=all [フアイル名]

[/text]

試しにこんなコードを書いてみた。

memory_leak.c

[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;

}

[/c]

なかなか、喧嘩を売っているコードだけれども、

これをCppCheckでチェックすると、案の定怒られる。(よしよし (^-^))

[text]

$ cppcheck –enable=all memory_leak.c

Checking memory_leak.c…

[memory_leak.c:12]: (error) Memory leak: p

Checking usage of global functions..

[/text]

自分で定義したメモリ獲得/解放関数のメモリリークをチェックする

次に、ユーザ定義したメモリ獲得/解放関数をチェックする。

普通、C標準のメモリ獲得/解放関数を直接使用することはなく、自前の関数でカスタマイズして使用することが多い。メモリアロケート関数を別ファイルで宣言してみる。

hoge_memory.c

[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;

}

[/c]

[text]

$ 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..

[/text]

Oh! 検出してくれないYo!!(゜д゜)/

こんなときは、–appendオプションを使用する。

使い方は、

[text]

cppcheck 窶錀-append=<メモリ獲得・解放関数定義file> <静的解析対象file>

[/text]

[text]

$ 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..

[/text]

これで、、メモリリークを検出しました。

メモリ二重解放を検出する

おまけ。メモリ二重解放もこのとおり発見できます!スゲー。

[c]

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;

}

[/c]

[text]

$ cppcheck –append=hoge_memory.c memory_leak.c

Checking memory_leak.c…

[memory_leak.c:15]: (error) Deallocating a deallocated pointer: p

[/text]

使われていない関数宣言

[text]

$ 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

[/text]