12

次のようなコーディング規則についてC++プロジェクトを自動的にチェックするための優れたツールはありますか?

スローされるすべてのオブジェクトは、std :: exceptionから派生したクラスである必要があります(つまり、std :: exceptionから派生していない他のタイプと同様に、またはthrow 42;エラーthrow "runtime error";としてフラグが立てられます)throw std::string("another runtime error");

結局、私はCppcheckのようなものを探していますが、チェックツールのソースコードをハックするよりも簡単な方法で新しいチェックを追加できます...ルールを設定できる素敵な小さなGUIを備えたものかもしれません。それらをディスクに書き込み、EclipseなどのIDEまたはJenkinsなどの継続的インテグレーションサーバーでルールセットを使用します。

4

3 に答える 3

10

私は現在のプロジェクトでいくつかの静的分析ツールを実行しました。ここにいくつかの重要なポイントがあります。

  • これらすべてのツールを実行するための単一のエントリポイントとしてVisualLintを使用しました。VLは、VSがサードパーティの静的分析ツールを実行するためのプラグインであり、レポートからソースコードへのシングルクリックルートを可能にします。報告されたエラーのさまざまなレベルから選択するためのGUIをサポートするほかに、自動バックグラウンド分析(進行中に修正されたエラーの数を示します)、単一ファイルの手動分析、色分けされたエラー表示、およびグラフ作成機能も提供します。VLインストーラーは、新しい静的分析ツールを追加しようとするときに非常に便利で非常に役立ちます(Google cpplintを使用し、Pythonがプリインストールされていない場合は、ActiveStateからPythonをダウンロードするのにも役立ちます)。VLについて詳しくは、こちらをご覧ください。http://www.riverblade.co.uk/products/visual_lint/features.html

  • VLで実行できる多数のツールの中から、ネイティブC ++コードで動作する3つのツール、cppcheck、Google cpplint、およびInspirelVera++を選択しました。これらのツールにはさまざまな機能があります。

  • Cppcheck:これはおそらく最も一般的なものであり、私たち全員が使用しています。それで、私は詳細をざっと見ます。非プリミティブ型の接尾辞増分の使用、empty()を使用する必要がある場合のsize()の使用に関する警告、変数のスコープ縮小、クラス定義内のメンバーの誤った名前修飾、誤った初期化順序などのエラーをキャッチすると言えば十分です。クラスメンバー、初期化の欠落、未使用の変数など。コードベースの場合、cppcheckは6Kエラーについて報告しました。いくつかの誤検知(未使用の関数など)がありましたが、これらは抑制されました。cppcheckの詳細については、http://cppcheck.sourceforge.net/manual.pdfを参照してください。

  • Google cpplint:これはPythonベースのツールで、ソースのスタイル違反をチェックします。この検証が行われるスタイルガイドは、http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml(基本的にはGoogleのC ++スタイルガイド)にあります。Cpplintは、コードベースで最大104Kのエラーを生成しました。そのほとんどのエラーは、空白(欠落または余分)、タブ、中括弧の位置などに関連しています。おそらく修正する価値のあるものは、Cスタイルのキャスト、欠落しているヘッダーです。

  • Inspirel Vera ++:これは、C ++ソースコードの検証、分析、および変換のためのプログラム可能なツールです。これは、機能的にはcpplintに似ています。使用可能なルールのリストはここにあります:http://www.inspirel.com/vera/ce/doc/rules/index.htmlおよび同様の使用可能な変換のリストはここにあります:http://www。 inspirel.com/vera/ce/doc/transformations/index.html。独自のルールを追加する方法の詳細については、http://www.inspirel.com/vera/ce/doc/tclapi.htmlを参照してください。私たちのプロジェクトでは、Vera ++は約90Kの問題を発見しました(20の奇妙なルールに対して)。

于 2012-05-03T10:46:59.480 に答える
6

今後の状態:GoogleのManuel Klimekは、C++コードのクエリと変換のためにGoogleで開発されたツールをClangメインラインに統合しています。

  • ツーリングインフラストラクチャがレイアウトされており、いっぱいになる可能性がありますが、すでに機能しています。主なアイデアは、アクションを定義し、選択したファイルに対してそれらのアクションを実行できるようにすることです。

  • Googleは、ASTをわかりやすい方法でクエリできるようにするための単純なC ++クラスとメソッドのセットを作成しました。ASTMatcherフレームワークは開発中であり、最終的には非常に正確なマッチングが可能になります。

現時点では実行可能ファイルを作成する必要がありますが、コードはライブラリとして提供されているため、編集する必要はなく、1回限りの変換ツールを単一のソースファイルで処理できます。


マッチャーの例(このスレッドにあります):目的は、(デフォルトのアロケーターを使用して)std::stringの結果から形成されたコンストラクターのオーバーロードへの呼び出しを見つけるstd::string::c_str()ことです。これは、代わりに単純なコピーに置き換えることができるためです。

ConstructorCall(
    HasDeclaration(Method(HasName(StringConstructor))),
    ArgumentCountIs(2),
    // The first argument must have the form x.c_str() or p->c_str()
    // where the method is string::c_str(). We can use the copy
    // constructor of string instead (or the compiler might share
    // the string object).
    HasArgument(
        0,
        Id("call", Call(
            Callee(Id("member", MemberExpression())),
            Callee(Method(HasName(StringCStrMethod))),
            On(Id("arg", Expression()))
        ))
    ),
    // The second argument is the alloc object which must not be
    // present explicitly.
    HasArgument(1, DefaultArgument())
)

ClangコンパイラのASTライブラリを使用しているため、アドホックツールと比較して非常に有望です。したがって、使用するマクロやテンプレートがどれほど複雑であっても、コードをコンパイルする限り、分析できることが保証されます。ただし、過負荷解決の結果に依存する複雑なクエリを表現できることも意味します。

このコードは、Clangライブラリ内から実際のASTノードを返すため、プログラマーはソースファイル内のビットとニットを正確に特定し、必要に応じて編集して微調整できます。

テキストマッチング仕様を使用することについての話がありましたが、C ++ APIから始める方が、非常に複雑になる(そして自転車を脱ぐ)ので、より良いと考えられました。PythonAPIが登場することを願っています。

于 2012-05-03T11:43:08.590 に答える
3

「スタイルチェッカー」の主な問題は、スタイルがアートのようなものであるということです。良いスタイルとそうでないものについては、誰もが異なる意見を持っています。その意味するところは、スタイルチェッカーは常に地元のアートの好みに合わせてカスタマイズする必要があるということです。

これを正しく行うには、シンボル定義、スコープルール、理想的にはさまざまな種類のフロー分析にアクセスできる完全なC++パーサーが必要です。AFAIK、CppCheckは正確な解析またはシンボルテーブル定義を提供しないため、エラーチェックを詳細かつ正確にすることはできません。CoverityとFortifyは、EDGフロントエンドを使用してこれらの方針に沿って何かを提供していると思います。彼らのツールがシンボルテーブルまたはデータフロー分析へのアクセスを提供するかどうかはわかりません。Clangがやってくる。

また、スタイルチェックを作成する方法も必要です。すべてのツールがASTとおそらくシンボルテーブルへのアクセスを提供していると思います。また、C ++のような大きな言語では難しい、ASTを詳しく知ることを犠牲にして、独自のチェックを手動でコーディングできます。CoverityとFortifyには、いくつかのチェックを指定するためのDSLのようなスキームがあると思います。

スタイルが正しくないコードを修正する場合は、コード表現を変更できるものが必要です。CoverityとFortifyはこのAFAIKを提供していません。Clangには、ASTを変更してコードを再生成する機能があると思います。ツリーハッキングロジックをコーディングして正しく実行するには、AST構造についてかなり深い知識が必要です。

DMS Software ReengineeringToolkitとそのC++フロントエンドは、これらの機能のほとんどを提供します。DMSは、C ++フロントエンドを使用して、ANSI C ++ 11、GCC4(C ++ 11拡張機能付き)およびMSVS 2010(C ++ 11拡張機能付き)を解析できます[2021年5月更新:完全なC++17およびほとんどのC++20]完全な型情報を使用してASTとシンボルテーブルを構築します。任意の式のASTノードのタイプを要求することもできます。現在、DMSは制御フローを計算しますが、C++のデータフローは計算しません。

AST APIを使用すると、任意のチェックを手続き的にコーディングできます。または、ASTに変更を加えて問題を修正すると、DMSのprettyprinterは、コメントと保存されたリテラル形式情報(基数など)を含む完全でコンパイル可能なソーステキストを再生成できます。これを行うには、他のツールと同じようにAST構造を知っている必要がありますが、DMS C ++文法規則と同型であるため、はるかに簡単に知ることができます。C ++フロントエンドには、C++文法が付属しています。[DMSはこれを可能にするためにGLRパーサーを使用します]。

さらに、C ++自体の表面構文を使用して、DMSのルール仕様言語を使用してパターンと変換を記述できます。OPを「非STL例外をスローしない」とコーディングする場合があります。

 pattern nonSTLexception(i: IDENTIFIER):statement
   = " throw \i; " if ~derived_from_STD_exception(i);

(メタ)引用符内のものは、パターンマッチングエスケープを含むC ++ソースコードです。たとえば、「\ i」は、ルールに従ってC++IDである必要があるプレースホルダー変数「i」を指します。「投げる\i;」全体 句はC++の「ステートメント」(C ++文法の非終端記号)である必要があります。ルール自体は主に一致する構文を表現しますが、一致するサブツリー(この場合は「\ i」が一致するもの)に適用されるセマンティックチェック(「〜is_valent_from_STD_exception」など)を呼び出すことができます。

このようなパターンを書く際に、ASTの形を知る必要はありません。パターンはそれを認識しており、自動的に照合されます。ASTウォーカーをコーディングしたことがある場合は、これがいかに便利であるかを理解できます。

一致はASTノードを認識しているため、正確な位置(ファイル/行/列)を認識しているため、正確な位置情報を含むレポートを簡単に生成できます。

カスタムルーチン"inherits_from_STD_exception"を追加して、そのルーチンに渡される識別子ツリーノードが(OPの必要に応じて)std::exceptionから派生したクラスであることを確認する必要があります。これには、シンボルテーブルで「std :: exception」を見つけ、識別子ツリーノードのシンボルテーブルエントリがクラス宣言であり、std :: exceptionまで(シンボルテーブルリンクをたどって)他のクラス宣言から一時的に継承することを確認する必要があります。シンボルテーブルエントリが見つかりました。

DMS変換ルールは、本質的に「これが表示された場合は、それをそれに置き換えます」というパターンペアです。

COBOLとC++の両方に対して、DMSを使用していくつかのカスタムスタイルチェッカーを構築しました。これはまだかなりの量の作業です。これは主に、C ++はかなり複雑な言語であり、チェックの正確な意味について慎重に考える必要があるためです。

トリッキーなチェックと、深い静的分析に分類され始めるテストでは、制御およびデータフロー情報にアクセスする必要があります。DMSは現在C++の制御フローを計算しており、データフロー分析に取り組んでいます(Java、IBM Enterprise COBOL、およびさまざまなCダイアレクトに対してこれをすでに実行しています)。分析結果はASTノードに関連付けられているため、パターンを使用してスタイルチェックの要素を探し、必要に応じてデータフローに従って要素を結び付けることができます。

すべてがDMSで(または実際に中途半端に正確な方法でC ++を処理する他のツールで)行われる場合、追加または複雑なスタイルチェックのコーディングは「便利」ではない可能性があります。あなたは「優れた技術的背景を持つ可能性がある」ことを期待するべきです。

于 2012-05-04T04:14:14.323 に答える