web-dev-qa-db-ja.com

未使用の関数について警告を受ける方法はありますか?

コンパイルユニット全体を含め、コードベースで未使用の関数を見つけたいのですが。コンパイラとしてgccを使用しています。

次に例を示します。

_foo.c_(適切な_foo.h_を想定):

_void foo() {
   ....
}

void bar() {
   ....
}
_

_main.c_:

_#include <stdio.h>
#include "foo.h"  

int main(void)  {
    bar();
    return 0;
}
_

この例では、foo()が使用されていないことを警告します。

_-Wunused-function_ gccオプションがあります。

_-Wunused-function_

静的関数が宣言されているが定義されていない場合、または非インライン静的関数が使用されていない場合に警告します。この警告は-Wallによって有効になります。

しかし、それは静的関数のためだけです-それは上の例で警告を生成しません。

また、これを行うことができるツール/スクリプト/その他のコンパイラの提案も受け入れますが、可能であればgccを使用することをお勧めします。

45
Timothy Jones

Caolan Mc Namara (LibreOffice開発者)は、LibreOfficeソースコードでこの種のことを検出する小さなツールを作成しました。それらには、LibreOfficeで使用されていない約1000の関数とメソッドがありました。彼のツールはそれらを削除するための重要な要素です。

callcatcher と呼ばれます。できる

定義された関数/メソッドを収集し、呼び出された/参照されたものを差し引く

アセンブラ出力で直接動作するため、x86およびx86_64アーキテクチャでのみ機能します。 this のような出力を生成できます。これを従来のコンパイルおよびgccへのリンク呼び出しと統合できます。

Caolanは、これがgccプラグインになるはずであることに同意します。

43
Coren

あなたが警告を求め、gccオプションを使用しないことを好むのを知っていますが、それは本当に簡単です。

リンカ最適化(--gc-sections)を使用して、アプリケーションから不要なコードを削除できます。

Gccのmanページから:

-gc-sections --no-gc-sections未使用の入力セクションのガベージコレクションを有効にします。このオプションをサポートしないターゲットでは無視されます。コマンドラインで--no-gc-sectionsを指定すると、このガベージコレクションを実行しないというデフォルトの動作に戻すことができます。

-gc-sectionsは、シンボルと再配置を調べて、使用する入力セクションを決定します。動的オブジェクトによって参照されるシンボルを含むセクションと同様に、エントリシンボルを含むセクションと、コマンドラインで定義されていないシンボルを含むすべてのセクションが保持されます。共有ライブラリを構築する場合、リンカーは可視シンボルが参照されていると想定する必要があることに注意してください。この最初のセクションのセットが決定されると、リンカは再配置によって参照されるセクションを使用済みとして再帰的にマークします。 --entryおよび--undefinedを参照してください。

このオプションは、部分リンクを実行するときに設定できます(オプション-rで有効化)。この場合、保持されるシンボルのルートは、-entryまたは--undefinedオプション、またはリンカースクリプトの "ENTRY"コマンドのいずれかで明示的に指定する必要があります。

4
eyalm

まず、そのような警告をプログラム全体に適用したい場合は、-fltoフラグ。個々のユニットのコンパイル時ではなく、リンク時に解決される必要があるため。しかし、私はGCCがこのような警告を提供することはないと思います。

次に、一般的なケースでは、それを提供することは賢明ではないことを理解します(たとえば、リンクされたlibcには、おそらくアプリケーションに必要ない多くの関数があるためです)。また、アプリケーションはdlsymトリックを使用して、明らかに呼び出されていない関数に到達できます...

ただし、これはGCCプラグインまたは [〜#〜] melt [〜#〜] 拡張機能の潜在的な使用例の良い例であり、各コールの発生をどこかに登録し、後でユーティリティが検出しますすべての非呼び出し関数。 (ただし、GCCの内部を理解する必要があるため、GCCのプラグインまたはMELT拡張機能のコーディングには少なくとも数日かかります)。

また、プロファイリング手法を使用して、動的に使用されない(呼び出されない)関数を取得することもできます。

メールで私にもっと尋ねてください。

Eclipse CDTにはコード分析があり、未使用の静的関数と未使用の関数宣言をマークするように設定できます(他の便利な機能の中でも)。すでに述べたように、リンカーのみが特定の(非静的)関数が特定のバイナリで使用されていないことを通知できました...

1
dbrank0

gprofは、私が推測する最も簡単なソリューションです。 -pgを実行したときにgmon.outを取得できるようにa.outオプションを付けてサンプルプログラムをコンパイルし、最後にgprof -z a.out gmon.out | tee output.txtを実行しました。 ] _。未使用のリストであなたの関数fooを見つけることができました!つまり、0回呼び出されます。 -zは、未使用のルーチンを追跡するためにgprofとともに使用するオプションです。

this スレッドのおかげで、適切なポインタが提供されました。

PS:gprofは、未使用の関数fooとともに、他の未使用のライブラリ関数を多数投げました。これをどのようにフィルタリングするか私は真剣に知りません:)

1
Pavan Manjunath