Table of Contents
Cppcheck は C/C++の静的解析ツールです。C/C++ コンパイラやその他の解析ツールとは異なり、シンタックスエラーを検出しません。 その代わりに、Cppcheckは、コンパイラが通常、検出に失敗するような種類のバグを検出します。このプロジェクトのゴールは、擬陽性 0 です。
サポートしているプログラムのソースコードとプラットフォーム:
さまざまなコンパイラの拡張構文や、インラインアセンブル等を含む、非標準的なソースコードをチェックできます。
Cppcheck は 最新のC++規格をサポートしている、あらゆるC++コンパイラでコンパイルできるようにしています。
Cppcheck は 十分なCPUパワーとメモリーのある、あらゆるプラットフォームで動作するようにしています。
Cppcheckに限界があることをご理解ください。Cppcheckの報告しているエラーに稀に間違いのあることがあります。また、Cppcheck が検出しないバグが残っていることもあります。
ソフトウェアを注意深くテストすれば、Cppcheckを使うより、より多くのバグを検出することができるでしょう。ソフトウェアを注意深く実装すれば、Cppcheckを使うより、より多くのバグを検出することができるでしょう。しかし、あなたのソフトウェアを実装するときやテストするときに見逃したバグのいくつかを Cppcheckが検出できるでしょう。
Table of Contents
これは単純なソースコードです。
int main() { char a[10]; a[10] = 0; return 0; }
このソースコードをfile1.c
に保存して次のコマンドを実行します。
cppcheck file1.c
cppcheck は次のように出力するでしょう。
Checking file1.c... [file1.c:4]: (error) Array 'a[10]' index 10 out of bounds
通常、プログラムは多くのソースファイルから構成されます。そして、それら全てをチェックしたいでしょう。Cppcheck は一つのディレクトリ以下の全てのソースファイルをチェックできます。
cppcheck path
ここで"path"はディレクトリのパスです。このようにすれば cppcheck はディレクトリ以下の全てのファイルを再帰的にチェックします。
Checking path/file1.cpp... 1/2 files checked 50% done Checking path/file2.cpp... 2/2 files checked 100% done
ファイルやフォルダをチェック対象から除外する方法は二つあります。最初の方法は、あなたがチェックしたいファイルやフォルダだけをcppcheckに指定することです。
cppcheck src/a src/b
src/a
と src/b
以下の全てのファイルだけをチェックします。
第二の方法は、-i
オプションと共に除外したいファイルやフォルダを指定することです。次のコマンドではsrc/c
以下のファイルをチェックしません。
cppcheck -isrc/c src
インクルードパスを追加するには-I
オプションに続けてパスを指定します。
Cppcheckのプリプロセッサは基本的に他のプリプロセッサと同様にインクルードを扱います。しかし、その他のプリプロセッサはヘッダファイルが見つからない場合に停止するのとは違って、cppcheckはただ単に、メッセージ情報を表示してソースコードの解析を続けます。
cppcheckは常にソースコード全体を確認する必要がないので、このような仕様になっています。実際に、全てのインクルードパスを与えないことを推奨しています。もちろん、クラスのメンバーの実装を確認した上でクラスの宣言をCppcheckでチェックするのは有用ではありますが、標準ライブラリのヘッダーをCppcheckに確認させるのは有用ではありません。というのは、チェックにかかる時間が長くなり、あまりよくない結果が表示されるからです。そのような場合、.cfg ファイル (後述します)によってcppcheckに関数や型の実装の情報を提供する方がよいでしょう。
メッセージのseverities(厳格度)には次のものがあります。:
バグが検出されたときに使用します。
防衛的プログラミングでバグを避けるための提案です。
コードの可読性の向上に関連した、スタイル関連の指摘(未使用関数、冗長なコードなど)
コードの高速化のための提案。これらの提案は、一般的な知識に基づいたものでしかありません。このメッセージの修正によって計測できるほど処理速度が向上するかどうかはわかりません。
移植性についての警告。64 bit CPUへの移植性。コンパイラ依存(独自拡張)ソースコードについての警告など。
設定上の問題設定を変更している間だけ有効にすることをお勧めします。
デフォルトではerror
のメッセージだけを表示します。--enable
を使用すると他のチェックを有効にできます。
# warning のメッセージを有効にします。 cppcheck --enable=warning file.c # performanceのメッセージを有効にします。 cppcheck --enable=performance file.c # informationのメッセージを有効にします。 cppcheck --enable=information file.c # 歴史的な理由により --enable=style を指定すると warning, performance, # portability と styleのメッセージを有効にします。古いxml形式を使用しているときには、これらの厳格度を"style"として報告されます。 cppcheck --enable=style file.c # warning と performance のメッセージを有効にします。 cppcheck --enable=warning,performance file.c # unusedFunction のチェックを有効にします。今回は --enable=styleでは有効にできない。 # というのは、これではライブラリではうまく動作しないからです。 cppcheck --enable=unusedFunction file.c # 全てのメッセージを有効にします。 cppcheck --enable=all
--enable=unusedFunction
はプログラム全体をチェックするときにだけ有効にしてください。また、--enable=all
もプログラム全体をチェックするときにだけ有効にしてください。というのは、unusedFunction チェックは、関数が呼び出されなかったときに警告するチェックだからです。関数呼び出しがチェック範囲にみつからなかったという可能性のノイズになります。
多くの場合、チェックの結果をファイルに保存したいと考えるでしょう。通常のシェルのリダイレクション機能を使って、エラー出力をファイルに保存することができます。
cppcheck file1.c 2> err.txt
オプションの-j
を使用してスレッド数を指定することができます。例えば、4スレッドを使ってフォルダ以下の全てのファイルをチェックする場合は次のように実行します。
cppcheck -j 4 path
このチェックでは未使用関数の検出(unusedFunction checking)は無効になることに注意してください。
あなたがターゲットとするプラットフォームの設定を使用すべきです。
デフォルトで、Cppcheckはネイティブのプラットフォームの設定を使用しますので、あなたのソースコードがローカルの環境でコンパイルし実行する場合には正常に動作するでしょう。
Cppcheck にはビルトインのプラットフォーム設定として、unix
とwindows
をターゲットにしたものがあります。コマンドラインオプションの--platform
を使ってプラットフォーム設定を指定できます。
XMLファイルで自身のプラットフォームにあった設定ファイルを作成することもできます。ここに例をあげます。:
<?xml version="1"?> <platform> <char_bit>8</char_bit> <default-sign>signed</default-sign> <sizeof> <short>2</short> <int>4</int> <long>4</long> <long-long>8</long-long> <float>4</float> <double>8</double> <long-double>12</long-double> <pointer>4</pointer> <size_t>4</size_t> <wchar_t>2</wchar_t> </sizeof> </platform>
Cppcheckはデフォルトでプリプロセッサのデファインのコンパイルスイッチ設定の組み合わせを全てチェックします。(ただし、これらのうち #error を除く)
これを変更するには -D を使います。また -D を使用した場合、cppcheckは与えられたコンパイルスイッチだけが有効でその他は設定されていないとしてチェックします。これは、コンパイラのように動作します。また、 --force
や
を使用すると、コンパイルスイッチの組み合わせの上限を上書きしてチェックすることができます。--max-configs
# 全てのコンパイルスイッチの組み合わせをチェックする。 cppcheck file.c # Aのコンパイルスイッチが有効になっている場合の組み合わせをチェックする cppcheck -DA file.c # check all configurations when macro A is defined cppcheck -DA --force file.c
また、もう一つのオプションに-U があります。これはシンボルのundefとなります。使用例:
cppcheck -UX file.c
これはXが定義されていないことを意味します。Cppcheck は Xが定義されている組み合わせをチェックしません。
Table of Contents
Cppcheckは出力をXML
形式に変更できます。XML出力には古いXML
形式(version 1) と新しいXML
形式(version 2)があります。可能であれば、新しい形式をご利用ください。
古い形式は後方互換性のためだけに残してあります。現在、変更の予定はありませんが、いつかは古い形式をサポートしなくなります。--xml
オプションでフォーマットを指定します。
新しい形式は古い形式にあったいくつかの問題を解消しています。新しい形式も、おそらくいつかは、新しい属性や要素を追加するなど変更されるかもしれません。Cppcheckでファイルをチェックし、新しいXML
形式で出力するコマンドのサンプルです。:
cppcheck --xml-version=2 file1.cpp
ここにバージョン2の出力の例を挙げます。:
<?xml version="1.0" encoding="UTF-8"?> <results version="2"> <cppcheck version="1.66"> <errors> <error id="someError" severity="error" msg="short error text" verbose="long error text" inconclusive="true" cwe="312"> <location file="file.c" line="1"/> </error> </errors> </results>
それぞれのエラーは<error>
要素に記載されます。属性:
id
エラーのidこれは、妥当なシンボル名です。
severity
以下のいずれかです: error
, warning
, style
, performance
, portability
, information
msg
短い形式のエラーメッセージ
verbose
長い形式のエラーメッセージ
inconclusive
この属性は、メッセージに疑いのある場合にのみ使用されます。
cwe
メッセージのCWE ID。こ属性は、メッセージのCWE IDが判明している場合のみ使用されます。
もし、テンプレートを使用して、出力の形式を変更することができます。
Visual Studioに互換性のある形式が必要な場合には、--template=vs
を使用します。
cppcheck --template=vs gui/test.cpp
このオプションは出力形式を次のように変更します。:
Checking gui/test.cpp... gui/test.cpp(31): error: Memory leak: b gui/test.cpp(16): error: Mismatching allocation and deallocation: k
gcc に互換性のある形式が必要な場合には、--template=gcc
を使用します。:
cppcheck --template=gcc gui/test.cpp
このオプションは出力形式を次のように変更します。:
Checking gui/test.cpp... gui/test.cpp:31: error: Memory leak: b gui/test.cpp:16: error: Mismatching allocation and deallocation: k
それ以外に、自分自身の作成したパターンで指定することもできます。例としてコンマ区切りで出力してみましょう。:
cppcheck --template="{file},{line},{severity},{id},{message}" gui/test.cpp
このオプションは出力形式を次のように変更します。:
Checking gui/test.cpp... gui/test.cpp,31,error,memleak,Memory leak: b gui/test.cpp,16,error,mismatchAllocDealloc,Mismatching allocation and deallocation: k
以下のようなフォーマット指定項目がサポートされています。
callstack ただし可能な場合に限る。
ファイル名
メッセージid
行数
長い形式のメッセージ
メッセージの種類、レベル
その他エスケープシーケンス \b (バックスペース), \n (改行), \r (改ページ) , \t (タブ) がサポートされています。
Table of Contents
ある種のエラーをフィルタリングしたい場合、出力を抑制することができます。
エラーの種類によって出力を抑制することができます。つぎのいずれかの形式で出力を抑制します。:
[error id]:[filename]:[line] [error id]:[filename2] [error id]
このerror id
は抑制したいエラーのidです。このエラーのIDを簡単に調べるには、--xml
オプションをコマンドラインで与えます。そのXML出力から、id
の文字列が取得できます。このエラーのIDに*
を指定して全ての種類のメッセージを抑制することができます。(これは指定したファイルに限ることができます。)
またfilename
にはワイルドキャラクターである、*
または ?
を含めることができます。前者には全ての文字列にマッチし、後者は任意の一文字にマッチします。またWindowsを含む全てのOSで、パス区切りに"/" を使うことをお勧めします。
--suppress=
のコマンドラインオプションを使用して、コマンドラインで抑制を指定することができます。例:
cppcheck --suppress=memleak:src/file1.cpp src/
エラー出力の抑制をソースコーオ中に直接、コメントの形で記載することもできます。このコメントには特別なキーワードを含めて記載します。ただし、インライン出力を抑制するコメントをソースコードに追加すると、ソースコードの可読性が少し悪くなってしまうかもしれません。
このソースコードは通常エラメッセージを出力する例です。:
void f() { char arr[5]; arr[10] = 0; }
前のソースコードに対する出力は次のようになります。:
# cppcheck test.c Checking test.c... [test.c:3]: (error) Array 'arr[5]' index 10 out of bounds
このエラーメッセージを抑制するには次のようなコメントを追加します。:
void f() { char arr[5]; // cppcheck-suppress arrayIndexOutOfBounds arr[10] = 0; }
これで、--inline-suppr オプションの準備ができました。次のようにcppcheckを起動するとエラーが抑制されます。:
cppcheck --inline-suppr test.c
Table of Contents
windows, posix, gtk, qt,他の外部のライブラリを使用した場合、Cppcheck
は外部の関数がどのようなものであるかがわかりません。Cppcheck
はそのため、メモリリークやバッファオーバーフロー、ヌルポインタのデリファレンスの可能性といったさまざまな問題が検出できません。これを解決するには設定ファイル(.cfg file)を使用します。
もしあなたが有名なライブラリの設定ファイルを作成したときには、私達のサイトにアップロードしてくれると非常に助かります。
あなたのプロジェクト専用の設定ファイルを作成し、使用することができます。そのためには、--check-library
と--enable=information
を使用して設定のためのヒントを入手します。
コマンドラインのcppcheck はカスタマイズした設定ファイル(.cfg files)を作業パスから読み込もうとします。作業パスはcppcheckを実行しているパスですでそこに設定ファイルがあると考えます。
GUIのcppcheckはプロジェクトのファイルパスから設定ファイルを読み込もうとします。カスタマイズした設定ファイル(.cfg file)は プロジェクトファイルの編集
ダイアログで確認できます。このタイアログを表示させるにはファイル
メニューから開いてください。
Cppcheck はリークのチェックについての設定できます。
ここにサンプルのプログラムがあります。:
void test() { HPEN pen = CreatePen(PS_SOLID, 1, RGB(255,0,0)); }
このサンプルには、リーソースのリークがあります。CreatePen()
はWindowsの関数でpenを作成します。しかし、Cppcheck はこの関数が返す値を解放しなければならないことがわかりません。そのためエラーメッセージは表示されません。:
# cppcheck pen1.c Checking pen1.c...
もし、windowsの設定ファイルをCppcheck
に提供すれば、この問題を指摘することができるようになります。:
# cppcheck --library=windows.cfg pen1.c Checking pen1.c... [pen1.c:3]: (error) Resource leak: pen
これが最小限のwindows.cfg
ファイルです:
<?xml version="1.0"?> <def> <resource> <alloc>CreatePen</alloc> <dealloc>DeleteObject</dealloc> </resource> </def>
しばしば、割り当てられたポインタを関数に渡すことがあります。例:
void test() { char *p = malloc(100); dostuff(p); }
もし設定ファイルがなく、Cppcheckがdostuff
の仕様を把握していなければ、Cppcheckはdostuff
がメモリーについて配慮しており、メモリーリークは発生しないと仮定します。
dostuff
がメモリーについて配慮せず、解放などを行なっていないことを指定するためには、leak-ignore
を使用します。:
<?xml version="1.0"?> <def> <function name="dostuff"> <leak-ignore/> <arg nr="1"/> <arg nr="2"/> </function> </def>
これとは逆にdostuff
がメモリーについて配慮している場合には次のように設定します。:
<?xml version="1.0"?> <def> <memory> <alloc>malloc</alloc> <dealloc>free</dealloc> <use>dostuff</use> </memory> </def>
なお、この
設定には論理的には全く無意味です。この設定がない場合でも同じエラーが表示されます。これは<use>
--check-library
のinformationメッセージを減らすために使用します。
ここにサンプルのプログラムがあります。:
void test() { char buffer1[1024]; char buffer2[1024]; CopyMemory(buffer1, buffer2, 1024); }
このプログラムのバグは buffer2 が初期化されていないことです。CopyMemory 関数の第二引数は初期化されている必要があります。しかし、Cppcheck
は関数に未初期化の変数を渡してもよいと仮定しています。:
# cppcheck uninit.c Checking uninit.c...
もし、windowsの設定ファイルをCppcheckに提供すれば、この問題を指摘することができるようになります。:
# cppcheck --library=windows.cfg uninit.c Checking uninit.c... [uninit.c:5]: (error) Uninitialized variable: buffer2
これが最小限のwindows.cfg
ファイルです。:
<?xml version="1.0"?> <def> <function name="CopyMemory"> <arg nr="1"/> <arg nr="2"> <not-uninit/> </arg> <arg nr="3"/> </function> </def>
Cppcheckは、関数にヌルポインタを渡してもよいと仮定しています。ここにサンプルのプログラムがあります。:
void test() { CopyMemory(NULL, NULL, 1024); }
MSDNの文書はこれが問題あるかないかを明らかにしていません。しかし、ここでは問題ありと仮定します。Cppcheck は関数にヌルポインタを渡してもよいと仮定していますので、エラーを出力しません。:
# cppcheck null.c Checking null.c...
もし、windowsの設定ファイルをCppcheck
に提供すれば、この問題を指摘することができるようになります。:
cppcheck --library=windows.cfg null.c Checking null.c... [null.c:3]: (error) Null pointer dereference
これが最小限のwindows.cfg
ファイルです:
<?xml version="1.0"?> <def> <function name="CopyMemory"> <arg nr="1"> <not-null/> </arg> <arg nr="2"/> <arg nr="3"/> </function> </def>
フォーマット文字列を扱う関数を定義できます。例:
void test() { do_something("%i %i\n", 1024); }
これについてもエラーは報告されません。:
# cppcheck formatstring.c Checking formatstring.c...
引数がフォーマット文字列であることを出力する設定ファイルが作成できます。設定ファイルの例です。:
<?xml version="1.0"?> <def> <function name="do_something"> <formatstr type="printf"/> <arg nr="1"> <formatstr/> </arg> </function> </def>
これで、Cppcheckはエラーを報告することができるようになりました。:
cppcheck --library=test.cfg formatstring.c Checking formatstring.c... [formatstring.c:3]: (error) do_something format string requires 2 parameters but only 1 is given.
このフォーマット文字列のtype
属性は次のどちらかになります。:
printf - printf のルールに従うフォーマット文字列
scanf - scanf のルールに従うフォーマット文字列
有効な値の範囲が定義できます。想像してください。:
void test() { do_something(1024); }
これについてもエラーは報告されません。:
# cppcheck valuerange.c Checking valuerange.c...
1024 が 範囲外の値であることを出力する設定ファイルが作成できます。設定ファイルの例です。:
<?xml version="1.0"?> <def> <function name="do_something"> <arg nr="1"> <valid>0:1023</valid> </arg> </function> </def>
これで、Cppcheckはエラーを報告することができるようになりました。:
cppcheck --library=test.cfg range.c Checking range.c... [range.c:3]: (error) Invalid do_something() argument nr 1. The value is 1024 but the valid values are '0-1023'.
validの要素で次のような表現が利用できます。:
0,3,5 => 0, 3 それに 5 だけが有効な値です。 -10:20 => -10 から 20 までの値(両端含む)が有効な値です。 :0 => 0または0未満の値が有効な値です。 0: => 0または0以上の値が有効な値です。 0,2:32 => 0 または2から32までの値(両端含む)が有効な値です。
いくつかの関数はバッファーを引数にとります。バッファの最小サイズを指定することができます。(要素数ではなくバイト数です。)想像してください。:
void test() { char str[5]; do_something(str,"12345"); }
これについてもエラーは報告されません。:
# cppcheck minsize.c Checking minsize.c...
設定ファイルで、例えば、引数1のバッファのサイズが引数2の文字列長より大きくなればならないと警告するような設定ファイルを作成できます。例を挙げます。:
<?xml version="1.0"?> <def> <function name="do_something"> <arg nr="1"> <minsize type="strlen" arg="2"/> </arg> <arg nr="2"/> </function> </def>
これで、Cppcheckはこのエラーを報告することができるようになりました。:
cppcheck --library=1.cfg minsize.c Checking minsize.c... [minsize.c:4]: (error) Buffer is accessed out of bounds: str
minsizes はいくつかの種類があります。:
バッファーのサイズが、その他の引数の文字列長より大きくなければなりません。例: std.cfg のstrcpyの設定を参照してください。
バッファーのサイズがその他の引数の値より大きくなればなりません。例: std.cfg のmemsetの設定を参照してください。
バッファーのサイズがその他の引数のバッファーのサイズより大きくなればなりません。例: std.cfg のstrcnpyの設定を参照してください
バッファーのサイズがその他の2つの引数の値の積より大きくなればなりません。典型的な使用例としては、一つの引数が構造体などの要素のサイズを指定し、もうひとつの引数が要素の個数を定義するような場合です。例: std.cfg のfreadの設定を参照してください
Cppcheck はこの関数がいつも値を返すとは仮定していません。ここにサンプルのプログラムがあります。:
void test(int x) { int data, buffer[1024]; if (x == 1) data = 123; else ZeroMemory(buffer, sizeof(buffer)); buffer[0] = data; // <- error: xが1でないとき初期化されていない }
理屈の上では、ZeroMemory
がプログラムを終了させてもバグはありません。そのため Cppcheckはエラーを報告しません。:
# cppcheck noreturn.c Checking noreturn.c...
しかし、--check-library
と--enable=information
をつかうとエラーが出力されます。:
# cppcheck --check-library --enable=information noreturn.c Checking noreturn.c... [noreturn.c:7]: (information) --check-library: Function ZeroMemory() should have <noreturn> configuration
もし適切な windows.cfg
が提供されていましたら、このバグは検出されます。:
# cppcheck --library=windows.cfg noreturn.c Checking noreturn.c... [noreturn.c:8]: (error) Uninitialized variable: data
これが最小限のwindows.cfg
ファイルです:
<?xml version="1.0"?> <def> <function name="ZeroMemory"> <noreturn>false</noreturn> </function> </def>
他になにも指定されていない限り、cppcheckは関数が返り値を無視していても問題ないと仮定します。:
bool test(const char* a, const char* b) { strcmp(a, b); // <- bug: strcmp の呼び出しは副作用を持ちませんが返り値を無視している。 return true; }
strcmp
が副作用を持つ場合、パラメータが関数に渡されている結果を無視しても問題はなく、このような仮定は正しいといえます。:
# cppcheck useretval.c Checking useretval.c...
もし適切なlib.cfg
が提供されていましたら、このバグは検出されます。:
# cppcheck --library=lib.cfg --enable=warning useretval.c Checking useretval.c... [noreturn.c:3]: (warning) Return value of function strcmp() is not used.
これが最小限のlib.cfg
ファイルです。:
<?xml version="1.0"?> <def> <function name="strcmp"> <use-retval/> </function> </def>
ライブラリはマクロプリプロセッサのdefineを使用することができます。例:
<?xml version="1.0"?> <def> <define name="NULL_VALUE" value="0"/> </def>
プリプロセッサの段階でソースコード中に "NULL_VALUE" が現れるごとに、"0"で置き換えます。
多くのソースコードで、プラットフォームに依存しない型をtypedefによって定義しています。"podtype"のタグによって、cppcheckがこれらのサポートするために必要な情報を提供できます。このような情報のない場合、cppcheckは次の例でみるような "uint16_t" 型を理解できません。
void test() { uint16_t a; }
そのため、未使用変数である、'a'が未使用であるとのメッセージが表示されません。
# cppcheck --enable=style unusedvar.cpp Checking unusedvar.cpp...
もし uint16_t が以下のように定義されていた場合、結果にメッセージが反映されます。
<?xml version="1.0"?> <def> <podtype name="uint16_t" sign="u" size="2"/> </def>
型のサイズはバイトサイズで指定します。符号の "sign" 属性は 符号ありの "s" か 符号無し "u" のどちらかです。これらの属性はオプションです。このライブラリを使用しますと、cppcheckはメッセージを表示できるようになります。
# cppcheck --library=lib.cfg --enable=style unusedvar.cpp Checking unusedvar.cpp... [unusedvar.cpp:2]: (style) Unused variable: a
C++ ライブラリの多くや STL 自身は、非常によく似た機能性をもつコンテナを提供する。ライブラリによってその動作をcppcheckに伝えることができる。それぞれのコンテナの設定にはユニークなIDが必要とします。コンテナの設定には、startPatternを加えることができます(オプション)。この startPatternはToken::Match パターンとendPattern に有効でなけばなりません。また、このendPatternはリンクしているトークンと比較されるものです。オブション属性の"inherits"は事前に定義されたコンテナのIDをとります。
<container>タグの内部で、<size>、<access>、<other>を選択して使用して関数を定義できます。これらのタグはそれぞれ、"resize" やその結果を与えるような動作を指定することができます。その例 "end-iterator"を示します。
次の例は、std::vectorの為の定義を示しています。std::vectorは"stdContainer"の定義に基づいていますが、ここには表示していません。:
<?xml version="1.0"?> <def> <container id="stdVector" startPattern="std :: vector <" inherits="stdContainer"> <size> <function name="push_back" action="push"/> <function name="pop_back" action="pop"/> </size> <access indexOperator="array-like"> <function name="at" yields="at_index"/> <function name="front" yields="item"/> <function name="back" yields="item"/> </access> </container> </def>
標準関数のstrcpyのための適切な設定は次のようになる。:
<function name="strcpy"> <leak-ignore/> <noreturn>false</noreturn> <arg nr="1"> <not-null/> </arg> <arg nr="2"> <not-null/> <not-uninit/> <strz/> </arg> </function>
この<leak-ignore/>
は、リークチェック中に関数呼び出しを無視するように、Cppcheckに伝えます。この関数は、割り当てられたメモリを解放しないことを意味しています。
この<noreturn>
は、この関数が、返り値を返すかどうかをCppchecに伝えます。
この関数は第一引数にポインタを取ります。しかしこのポインタは、ヌルポインタであってはなりません。というのは<not-null>
が使用されているからです。
この関数は第二引数にポインタを取ります。このポインタはヌルポインタであってはなりません。また、このポインタは初期化されたデータを指していなければなりません。<not-null>
と <not-uninit>
は正しく使用されています。さらにいえば、このポインタは0終端文字列(zero-terminated string)でなければなりません。そのため<strz>が使用されています。
Table of Contents
正規表現を使用して、ユーザーがルール(rule)を定義することができます。
これらのカスタムルールは、ソースコードを高度に分析した結果を使用することができません。しかしソースコード中の非常にシンプルなパターンについて簡単にルールを作成することができます。
ルールの作成を始めるには次の関連記事を参照してください。:
http://sourceforge.net/projects/cppcheck/files/Articles/
ルールのファイルフォーマットは次のとおりです。:
<?xml version="1.0"?> <rule> <tokenlist>LIST</tokenlist> <pattern>PATTERN</pattern> <message> <id>ID</id> <severity>SEVERITY</severity> <summary>SUMMARY</summary> </message> </rule>
patternタグ中にCDATAを含めた場合、XMLに干渉する可能性がありますので使用時はご注意ください。:
<![CDATA[some<strange>pattern]]>
この<tokenlist>
要素はオプションです。この要素がある場合、どのトークンをチェックするかを指示することができます。このLIST
はdefine
, raw
, normal
, simple
のいずれかです。
#define プリプロセッサの記述をチェックするために使用します。
プリプロセッサの出力をチェックするために使用します。
normal
のトークンリストをチェックするために使用します。ソースコードをある程度、単純化した結果をチェックすることになります。
単純なトークンリストをチェックするために使用します。ソースコードを完全に単純化した結果をチェックすることになります。ほとんどの Cppcheckのチェックには、この 単純ばトークンリストを使用します。
もし<tokenlist>要素を省略した場合、simple
が使用されます。
このSEVERITY
にはCppcheck
の厳格度(severities)である、次のいずれかを指定します。: information
, performance
, portability
, style
, warning
,error
Table of Contents
Cppcheckのアドオンは、個別のスクリプトや個別のプログラムとして実装されています。Cppcheckのアドオンを使用すると次のような利点があります。
洗練された分析の結果を使用した個別の、外部チェックを追加できます。
ソースコードが可視化できます。
その他
現在、アドオンを使用するには2段階の操作が必要です。:
Cppcheckを実行し、ダンプファイルを生成します。
アドオンでダンプファイルを処理します。
--dump
フラグを使用するとダンプファイルを生成できます。foo/ フォルダ以下の全てのソースファイルからダンプファイルを生成するには次のようにします。
cppcheck --dump foo/
foo/ フォルダ以下の全てのダンプファイルをアドオンで処理するには次のようにします。
python addon.py foo/*.dump
Cppcheck は XML形式でダンプファイルを生成できます。このファイルには以下のようなものが含まれています。:
トークンリスト(Token list)
シンタックスツリー(Syntax trees)
シンボルデータベース(関数、クラス、変数、スコープ)
既知の値(value flow analysis)
Cppcheckはアドオンを直接実行することはできません。直接実行するためにインターフェースはありません。これは、次のような制限がないことを意味します。:
アドオンを作成しリリースする際に、どのようなライセンスでも適用できます。
アドオンの作成に、どのようなスクリプト言語やプログラミング言語で作成できます。
アドオン作成者がユーザーインターフェースと出力を決定できます。
警告の生成以外の目的にもアドオン使用できます。
アドオン作成者の利便性のために、Cppcheck プロジェクトは PythonからCppcheckのデータにアクセスするための cppcheckdata.pyを提供しています。cppcheckdata.pyの使用はオプションです。
Script:
import sys import cppcheckdata def printtokens(data): for token in data.tokenlist: print(token.str) for arg in sys.argv[1:]: printtokens(cppcheckdata.parse(arg))
Script:
import sys import cppcheckdata def printfunctions(data): for scope in data.scopes: if scope.type == 'Function': print(scope.className) for arg in sys.argv[1:]: printfunctions(cppcheckdata.parse(arg))
cppcheckのXML出力をHTML形式に変更できます。これを利用するには、Python と pygments module (http://pygments.org/) が必要です。Cppcheckのソースツリーにhtmlreport
というフォルダがあります。このフォルダには、CppcheckのXMLファイルをHTML出力に変換するスクリプトがあります。
このコマンドでヘルプ画面を生成するには次のように実行します。
htmlreport/cppcheck-htmlreport -h
出力画面には次の内容が表示されます。:
Usage: cppcheck-htmlreport [options] Options: -h, --help show this help message and exit --file=FILE The cppcheck xml output file to read defects from. Default is reading from stdin. --report-dir=REPORT_DIR The directory where the html report content is written. --source-dir=SOURCE_DIR Base directory where source code files can be found.
使用例:
./cppcheck gui/test.cpp --xml 2> err.xml htmlreport/cppcheck-htmlreport --file=err.xml --report-dir=test1 --source-dir=.
Table of Contents
結果はリスト表示されます。
メニューを操作して、メッセージの種類毎に表示/非表示を切り替えできます。
結果をXML ファイルに保存して、後で確認できます。Save results to file
と Open XML
を参照してください。
プロジェクトファイルは、プロジェクト固有の設定を保存するのに使用します。固有の設定には次のものがあります。:
インクルードパス
プリプロセッサのdefine
このマニュアルの3 章にあるように、全てのコンパイルスイッチの組み合わせをチェックします。コンパイルスイッチの組み合わせを制限したい場合にだけ、プリプロセッサのdefineを指定してください。