レガシーC / C ++プロジェクトでのデッドコード検出[終了]
-
04-07-2019 - |
質問
C / C ++コードでデッドコードを検出する方法を教えてください。使用するかなり大きなコードベースがあり、少なくとも10〜15%がデッドコードです。この領域を識別するUnixベースのツールはありますか?一部のコードはまだ多くのプリプロセッサを使用していますが、自動化されたプロセスで処理できますか?
解決
このためにコードカバレッジ分析ツールを使用し、コード内の未使用のスポットを探すことができます。
gccツールチェーンの一般的なツールはgcovとグラフィカルフロントエンドlcov( http:/ /ltp.sourceforge.net/coverage/lcov.php )。
gccを使用する場合は、gcovサポートを使用してコンパイルできます。これは、「-coverage」フラグによって有効になります。次に、このgcov対応ビルドでアプリケーションを実行するか、テストスイートを実行します。
基本的に、gccはコンパイル中に余分なファイルをいくつか出力し、アプリケーションは実行中にカバレッジデータもいくつか出力します。これらすべて(.gcdoおよび.gcdaファイル)を収集する必要があります。ここでは詳細に説明しませんが、GCOV_PREFIXとGCOV_PREFIX_STRIP ...の2つの環境変数を適切な方法で適切に収集する必要があります。
実行後、すべてのカバレッジデータをまとめて、lcov toolsuiteで実行できます。少し複雑ですが、さまざまなテスト実行からのすべてのカバレッジファイルのマージも可能です。
とにかく、いくつかのカバレッジ情報を表示する一連の素晴らしいWebページがあり、カバレッジがないため使用されなかったコードの一部を指摘します。
もちろん、コードの一部がどのような状況でも使用されていないかどうかを再確認する必要があります。多くは、テストがコードベースをどの程度適切に実行するかにかかっています。しかし、少なくとも、これはデッドコード候補の可能性についてのアイデアを提供します...
他のヒント
-Wunreachable-codeを使用してgccでコンパイルします。
バージョンが新しいほど、より良い結果が得られると思いますが、彼らが積極的に取り組んでいるものだという印象は間違っているかもしれません。これはフロー分析を行うことに注意してください。ただし、「コード」について説明しているとは思いません。プリプロセッサを離れる頃にはすでに死んでいます。コンパイラによって解析されることはないからです。また、検出されません。呼び出されないエクスポートされた関数、またはそのパラメーターで関数を呼び出さないために偶然に不可能になる特別なケース処理コード-そのためのコードカバレッジが必要です(そして、ユニットテストではなく機能テストを実行します。ユニットテストは100%のコードカバレッジを想定し、したがってアプリケーションに関する限り「デッド」なコードパスを実行します)。それでも、これらの制限を念頭に置いて、コードベースで最も完全にボリックス化されたルーチンを簡単に見つけることができます。
アプローチは、可用性(自動化)テストに依存します。十分な量の機能をカバーすると信頼できるテストスイートがある場合は、以前の回答が既に示したように、カバレッジ分析を使用できます。
それほど幸運でない場合は、 SciTools '多くの組み込み分析レポートを使用してコードを分析するのに役立つことを理解してください。このツールでの私の経験は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として宣言されておらず、そこから呼び出されていないことをコンパイラーが認識できないため、残念ながらこの動作は正しいです。確実にできるのはリンカーのみです。
Cコードのみで、プロジェクト全体のソースコードを想定 利用できる場合は、オープンソースツール Frama-C で分析を開始します。 GUIで赤を表示するプログラムのステートメントは次のとおりです。 デッドコード。
「デッドコード」がある場合問題、あなたも興味があるかもしれません
「スペアコード」を削除します。実行されるが実行されないコード
最終結果に貢献します。これを提供する必要があります
I / O関数の正確なモデル化(望まないでしょう)
「スペア」と思われる計算を削除するにはしかし
printf
の引数として使用されます)。 Frama-Cには、スペアコードを指定するオプションがあります。
Mozilla と Open Office には独自のソリューションがあります。
このようなデッドコード分析には、プロジェクト全体のグローバル分析が必要です。翻訳ユニットを個別に分析してこの情報を取得することはできません(完全に単一の翻訳ユニット内にある場合、死んだエンティティを検出できますが、私はそれが本当に探しているとは思いません)。
すべてのコンパイルユニットを一度に解析し、すべてのシンボルテーブルを構築し、すべての参照を追跡することにより、DMS Software Reengineering Toolkitを使用してこれをJavaコードに正確に実装しました。参照も外部APIアイテムであるという主張もないトップレベルの定義は無効です。また、このツールはデッドコードを自動的に取り除きます。最後に、必要なものを選択できます。デッドエンティティのレポート、またはそれらのエンティティのストリップされたコード。
DMSは、さまざまな方言のC ++も解析します(EDIT Feb 2014: MSおよびGCCバージョンのC ++ 14 [2017年11月編集:現在C ++ 17] )および必要なすべてのシンボルテーブルを構築します。デッドリファレンスの追跡は、その時点から簡単になります。 DMSを使用してそれらを除去することもできます。 http://www.semanticdesigns.com/Products/DMS/DMSToolkit.htmlをご覧ください。 a>
Bullseye カバレッジツールが役立ちます。ただし、無料ではありません。