C / C ++コードでデッドコードを検出するにはどうすればよいですか?使用するコードベースがかなり大きく、少なくとも10〜15%がデッドコードです。この領域を識別するためのUnixベースのツールはありますか?一部のコードはまだ多くのプリプロセッサを使用していますが、自動化されたプロセスでそれを処理できますか?
8 に答える
これには、コード カバレッジ分析ツールを使用して、コード内の未使用のスポットを探すことができます。
gcc ツールチェーンの一般的なツールは、グラフィカル フロントエンド lcov ( http://ltp.sourceforge.net/coverage/lcov.php )と共に gcovです。
gcc を使用する場合、「--coverage」フラグによって有効にされる gcov サポートでコンパイルできます。次に、この gcov 対応ビルドでアプリケーションを実行するか、テスト スイートを実行します。
基本的に、gcc はコンパイル中にいくつかの追加ファイルを発行し、アプリケーションは実行中にいくつかのカバレッジ データも発行します。これらすべて (.gcdo および .gcda ファイル) を収集する必要があります。ここでは詳しく説明しませんが、適切な方法でカバレッジ データを収集するには、おそらく 2 つの環境変数を設定する必要があります: GCOV_PREFIX と GCOV_PREFIX_STRIP...
実行後、すべてのカバレッジ データをまとめて、lcov ツールスイートで実行できます。少し複雑ではありますが、異なるテスト実行からのすべてのカバレッジ ファイルをマージすることも可能です。
とにかく、いくつかのカバレッジ情報を表示し、カバレッジがなく、したがって使用されなかったコードの断片を指摘する、すばらしい一連の Web ページが作成されます。
もちろん、コードの一部がどのような状況でも使用されていないかどうかを再確認する必要があります。多くの場合、テストがコードベースをどれだけ適切に実行するかに依存します。しかし、少なくとも、これは考えられるデッドコードの候補についてのアイデアを提供します...
-Wunreachable-code を指定して gcc でコンパイルします。
バージョンが新しいほど良い結果が得られると思いますが、彼らが積極的に取り組んでいるものであるという私の印象は間違っているかもしれません. これはフロー分析を行うことに注意してください。ただし、コンパイラによって解析されないため、プリプロセッサを離れるまでに既に死んでいる「コード」についてはわかりません。また、たとえば、呼び出されることのないエクスポートされた関数や、そのパラメーターを使用して関数を呼び出すものがないためにたまたま不可能な特別なケースの処理コードも検出しません。単体テスト. 単体テストが想定されています100% のコード カバレッジを持つため、アプリケーションに関する限り「デッド」なコード パスを実行します)。それでも、これらの制限を念頭に置くと、コード ベース内で最も完全にボリックスされたルーチンを見つけ始めるための簡単な方法です。
Cコードの場合のみ、プロジェクト全体のソースコードが利用可能であると想定して、オープンソースツールFrama-Cを使用して分析を開始します。GUIに赤で表示されるプログラムのステートメントは、デッドコードです。
「デッドコード」の問題がある場合は、実行されても最終結果に寄与しない「スペアコード」を削除することもできます。これには、I / O関数の正確なモデル化を提供する必要があります(「スペア」のように見えるが、の引数として使用される計算を削除する必要はありませんprintf
)。Frama-Cには、スペアコードを指摘するためのオプションがあります。
MozillaとOpen Officeの両方に独自のソリューションがあります。
アプローチは、可用性 (自動) テストによって異なります。十分な量の機能をカバーすると信頼できるテスト スイートがある場合は、以前の回答が既に示唆したように、カバレッジ分析を使用できます。
運が悪い場合は、組み込みの分析レポートを多数使用してコードを分析するのに役立つSciTools ' Understandingなどのソース コード分析ツールを調べることをお勧めします。そのツールでの私の経験は 2 年前にさかのぼるので、詳細をお伝えすることはできませんが、覚えているのは、バグ修正と質問への回答のターンアラウンド タイムが非常に短いという印象的なサポートがあったことです。
他の多くのツールもリストしている静的ソースコード分析に関するページを見つけました。
それでも十分に役に立たず、プリプロセッサ関連のデッド コードを見つけることに特に関心がある場合は、コードに関する詳細を投稿することをお勧めします。たとえば、主に #ifdef 設定のさまざまな組み合わせに関連している場合は、スクリプトを記述して、設定 (の組み合わせ) を決定し、実際には構築されない組み合わせを見つけることができます。
g++ 4.01 -Wunreachable-code は、関数内で到達できないコードについて警告しますが、未使用の関数については警告しません。
int foo() {
return 21; // point a
}
int bar() {
int a = 7;
return a;
a += 9; // point b
return a;
}
int main(int, char **) {
return bar();
}
g++ 4.01 はポイント b について警告を発行しますが、このファイルでは到達できないにもかかわらず、foo() (ポイント a) については何も言いません。コンパイラは、関数 foo() が他のコンパイル単位で extern として宣言されておらず、そこから呼び出されていないことを認識できないため、この動作は正しいですが、残念です。リンカーだけが確認できます。
このようなデッド コード分析には、プロジェクト全体のグローバル分析が必要です。翻訳単位を個別に分析しても、この情報を取得することはできません (完全に 1 つの翻訳単位内にある場合は、死んだエンティティを検出できますが、それはあなたが本当に探しているものではないと思います)。
DMS Software Reengineering Toolkit を使用して、関連するすべてのコンパイル ユニットを一度に解析し、すべてのシンボル テーブルを構築し、すべての参照を追跡することにより、Java コードにこれを正確に実装しました。参照がなく、外部 API アイテムであるという主張がないトップ レベルの定義は無効です。このツールはまた、デッド コードを自動的に削除します。最後に、必要なものを選択できます: デッド エンティティのレポート、またはそれらのエンティティを削除したコード。
DMS はまた、さまざまな方言で C++ を解析し (2014 年 2 月編集: C++14 の MS および GCC バージョンを含む [2017 年 11 月編集: C++17 になりました] )、必要なすべてのシンボル テーブルを構築します。無効な参照を追跡することは、その時点から簡単です。DMS を使用してそれらを取り除くこともできます。http://www.semanticdesigns.com/Products/DMS/DMSToolkit.htmlを参照してください。
ブルズアイカバレッジツールが役立ちます。ただし、無料ではありません。