2012-02-01 5 views
43

私はコードベースで未使用の関数を見つけたいと思っています。私はコンパイラとして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に固執したいと思いますが、ツール/スクリプト/他のコンパイラの提案も受け付けます。

+6

デフォルトでは、未使用の非静的関数について警告しないのがよい理由があります。静的でない関数はpublicインターフェイスの一部です。gccが生成した.oファイルをリンカーに簡単に送り込んで.aまたは.soライブラリを生成することができます。これらの非静的関数はすべてリンクライブラリと一緒に。しかし、これはまだ大きな疑問であり、私は有益な答えを期待しています。 –

+3

絶対に、デフォルトではオンであってはいけません。機能が存在する場合、最終的なリンク時にそれを有効にすることができます:) –

+1

関連http://gcc.gnu。org/ml/gcc-help/2003-08/msg00072.html? –

答えて

41

Caolan Mc Namara、LibreOfficeの開発者は、LibreOfficeのソースコードでこの種のものを検出するための小さなツールを作った。彼らはLibreOfficeで数千の関数&メソッドを使用していませんでした。彼のツールはそれらを削除するための重要な要素です。

callcatcherと呼ばれています。それ

は、アセンブラ出力に直接働くので、それが唯一のx86とx86_64アーキテクチャのために働く定義された関数/メソッドを収集し、呼ばれる加算/減算

を参照することができます。それはthisのような出力を生成することができます。 gccの従来のコンパイルおよびリンク呼び出しと統合することができます。

Caolanはgccプラグインになることに同意します。

+0

これは、まさに私が望むものです。ありがとうございました! –

+4

それは素晴らしいです。あなたの娯楽価値のために、私が仕事をしているプロジェクトには** 1257の未使用機能**があります。私は、このコードベースにはいくつかあるかもしれないという印象を受けました... –

3

最初に、このような警告をプログラム全体に渡す場合は、確実に-fltoフラグが必要です。これはリンク時に解決されるべきであり、個々のユニットのコンパイル時ではないからです。しかし、私はGCCがこのような警告を提供するとは思わない。

一般的なケースでは、それを提供することは賢明ではないことを理解しています(たとえば、リンクされたlibcにはアプリケーションには必要のない機能がたくさんあるため)。また、アプリケーションは、しかし、それはで、どこかに各呼び出しの発生を登録しますGCCのプラグインやMELT拡張のための潜在的なユースケースの良い例である

...どうやら差し出がましい機能に到達するためにdlsymトリックを使用することができますそれ以降のユーティリティはすべての非関数を検出します。 (しかしGCCのプラグインやMELT拡張をコーディングするには少なくともGCCの内部を理解する必要があるので、少なくとも数日はかかります)。

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

メールでお気軽にお問い合わせください。

+1

+1ありがとうGCCプラグインのルートを終えると、私はほとんど確実にあなたにメールを送ります:) –

+0

MELTの拡張機能はC言語のGCCプラグインよりも助けになります。 –

+0

@BasileStarynkevitch:多分あなたCaolan Mc Namaraがこれについて何をしたのかを見ることに興味があります。詳細は私の答えを見てください。 – Coren

3

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

リンカーの最適化(--gc-sections)を使用すると、アプリケーションからデッドコードを削除できます。 GCCのmanページから

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

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

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

+3

悲しいことに、私はバイナリからコードを削除するつもりはありません - ソースのどの部分がクリーンアップできるかを調べることを検討しています –

+5

正しく覚えていれば、冗長オプションがあります。 gc-sectionsによって行われました。私はそれが "--print-gc-sections"だと思います。 – eyalm

1

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

1

gprofは私が推測する最も簡単な解決策です。 -pgオプションを設定したサンプルプログラムをコンパイルし、a.out(gprofは後で使用できます)を実行してからgprof -z a.out gmon.out | tee output.txtを実行したときにgmon.outを取得しました。私は未使用のリストにあなたの機能fooを見つけることができました!すなわち0回と呼ばれます。 -zは、使用されていないルーチンを追跡するためにgprofと共に使用するオプションです。

適切なポインタのthisスレッドのおかげで!

PS:gprofは、未使用の関数fooと一緒に使用されていない他のライブラリ関数の数を投げた。私は真剣にこれをフィルタリングする方法を知らない:)

関連する問題