コードのどの部分が使用されていないかを知るにはどうすればよいですか?


312

未使用のコードを削除することになっているレガシーC ++コードがあります。問題は、コードベースが大きいことです。

どのコードが呼び出されない、または使用されないかを知るにはどうすればよいですか?


4
コードクエリ言語を使用すると、プロジェクト全体の見方がよくなると思います。C ++の世界についてはよくわかりませんが、cppdepend.com(これは無料ではありません)があるようです。このようなものが無料で利用できる場合があります。もう1つは、何らかのリファクタリングを行う前に、現時点でユニットテストがない場合は、ユニットテストを行うのが常識です。単体テストでできることは、コードカバレッジツールでコードをプロファイルすることです。これにより、コードをカバーできない場合に、デッドコードを取り除くのに役立ちます。
ビスワナート2011年

3
こちらのリファレンスを確認してください:en.wikipedia.org/wiki/Unreachable_code
Martin York

6
同様のトピックを見つけました。stackoverflow.com/questions/229069/...
ウマグマ

3
うん、C ++の面白い点の1つは、「未使用」の関数を削除しても、プログラムの結果が変更される可能性があることです。
MSalters '27年

1
@MSalters:それは興味深いものです...そのためには、特定の呼び出しに対してオーバーロードセットのどの関数が選択されるかについて話し合う必要がありますよね?私の知る限り、両方の名前が付けられた2つの関数があり、1番目f()f()明確に解決される呼び出しがある場合、3番目の関数を追加するだけでその呼び出しを2番目に解決するf()ことはできません。 "3番目の関数を追加すると、呼び出しが不明確になり、プログラムのコンパイルができなくなります。反例を見るのが好き(=恐ろしい)。
j_random_hacker 2011年

回答:


197

未使用のコードには2つの種類があります。

  • ローカルのパス、つまり一部の関数では、一部のパスまたは変数が使用されていません(または使用されていますが、書き込まれているが読み取られていないなど、意味のない方法で使用されています)
  • グローバルなもの:決して呼び出されない関数、決してアクセスされないグローバルオブジェクト

最初の種類については、優れたコンパイラーが役立ちます。

  • -Wunused(GCC、Clang)は未使用の変数について警告する必要があります。Clang未使用アナライザーは、(使用されていても)読み取られない変数について警告するようにインクリメントされています。
  • -Wunreachable-code2010年削除された古いGCC )は、アクセスされないローカルブロックについて警告する必要があります(これは、常にtrueと評価される早期の復帰または条件で発生します)。
  • catchコンパイラーは通常、例外がスローされないことを証明できないため、未使用のブロックについて警告するオプションはありません。

2番目の種類の場合は、はるかに困難です。静的にはプログラム全体の分析が必要であり、リンク時の最適化によって実際にデッドコードが削除される場合でも、実際にはプログラムは実行時に変換されているため、ユーザーに意味のある情報を伝えることはほとんど不可能です。

したがって、2つのアプローチがあります。

  • 理論的なものは、静的アナライザーを使用することです。コード全体を一度に詳細に調べ、すべてのフローパスを見つけるソフトウェアです。実際には、ここで機能するものはわかりません。
  • 実用的な方法は、ヒューリスティックを使用することです。コードカバレッジツールを使用します(GNUチェーンではgcov。です。コンパイル中に特定のフラグを渡して、正しく機能するようにしてください)。さまざまな入力(ユニットテストまたは非回帰テスト)の適切なセットを使用してコードカバレッジツールを実行します。デッドコードは必然的に到達されていないコード内にあるため、ここから開始できます。

このテーマに非常に興味があり、実際にツールを自分で作成する時間と傾向がある場合は、Clangライブラリを使用してそのようなツールを作成することをお勧めします。

  1. Clangライブラリを使用してAST(抽象構文ツリー)を取得する
  2. エントリポイント以降からマークアンドスイープ分析を実行する

Clangがコードを解析してオーバーロードの解決を実行するため、C ++言語のルールに対処する必要がなく、目の前の問題に集中することができます。

ただし、理由のないサードパーティのコードによって呼び出される可能性があるため、この種の手法では未使用の仮想オーバーライドを識別できません。


7
とても素敵です、+ 1。どのような状況でも実行されないように静的に決定できるコードと、特定の実行では実行されないが潜在的に実行できるコードを区別してほしいと思います。前者は私が考える重要なものであり、あなたが言うように、プログラム全体のASTを使用した到達可能性分析はそれを得る方法です。(foo()それだけで表示されるときに「呼び出された」とマークされないようにif (0) { foo(); }することはボーナスになりますが、特別なスマートが必要です。)
j_random_hacker

@j_random_hacker:おそらく、CFG(Control-Flow Graph)を使用する方がいいと思う(今の例のおかげ)。私はClangがあなたが言及したようなトートロジーの比較について発言することに熱心であり、CFGを使用することで早期にデッドコードを見つける可能性があることを知っています。
Matthieu M.

@Matthieu:ええ多分CFGはASTの代わりに私の意味でもあります:)つまり、頂点は関数であり、xがyを呼び出す可能性があるときはいつでも、関数xから関数yへのエッジがあるダイグラフです。(そして、オーバーロードされた関数はすべて別個の頂点によって表されるという重要な特性により、Clangがあなたのためにそれを行うように聞こえますよね!)
j_random_hacker

1
@j_random_hacker:CFGは、条件付きステートメントに基づいて、あるブロックから別のブロックへのリンクを持つブロックで実行されるすべてのコードを表すため、実際には単純なダイグラフよりも複雑です。主な利点は、静的にデッドであると判断できるコードのプルーニングに自然に適していることです(識別可能な到達不能ブロックを作成します)。そのため、ASTよりもCFGを活用して、目的のダイグラフを構築する方が適切です。話している...私は思う:)
Matthieu M.

1
@j_random_hacker:実際にはClangのASTは、すべてを明示的に(またはほぼ...)作成します。これは、単にコードをコンパイルするためではなく、コードを操作するためのものだからです。初期化リストには明らかにそのような暗黙の変換がASTに現れないという問題があるため、現時点では実際に議論がありますが、修正されると思います。
Matthieu M.

35

未使用の関数全体(および未使用のグローバル変数)の場合、GCCとGNU ldを使用している場合、GCCは実際にほとんどの作業を実行できます。

ソースをコンパイルするときはとを使用-ffunction-sections-fdata-sections、次にリンクするときはを使用します-Wl,--gc-sections,--print-gc-sections。リンカは、呼び出されなかったために削除できるすべての関数と、参照されなかったすべてのグローバルをリストします。

(もちろん、この--print-gc-sections部分をスキップして、リンカーに関数をサイレントに削除させて、ソースに残しておくこともできます。)

注:これは未使用の完全な関数のみを検索します。関数内のデッドコードについては何も行いません。ライブ関数のデッドコードから呼び出された関数も保持されます。

一部のC ++固有の機能も問題を引き起こします。特に、

  • 仮想機能。存在するサブクラスと実行時に実際にインスタンス化されるサブクラスを知らなければ、最終的なプログラムに存在する必要がある仮想関数を知ることはできません。リンカはそれについて十分な情報を持っていないので、それらのすべてを保持する必要があります。
  • コンストラクターを持つグローバルとそのコンストラクター。一般に、リンカはグローバルのコンストラクタに副作用がないことを認識できないため、実行する必要があります。明らかに、これはグローバル自体も維持する必要があることを意味します。

どちらの場合も、何も使用仮想関数やグローバル変数コンストラクタでも周りに保つ必要があります。

さらに注意が必要なのは、共有ライブラリを構築している場合、GCCのデフォルト設定では共有ライブラリのすべての関数がエクスポートされるため、リンカーに関する限り、その関数が「使用」されることです。これを修正するには、デフォルトでエクスポートではなくシンボルを非表示に設定し(を使用するなど-fvisibility=hidden)、エクスポートする必要のあるエクスポートされた関数を明示的に選択します。


素晴らしい実用的なアドバイス。どこでも使用されないことがわかっている関数のリストを取得するだけで(このリストが完全ではない場合でも)、思いがけない成果がたくさん得られます。
j_random_hacker

これは、インスタンス化されていないテンプレートでは機能しないと思います。
JakubKlinkovský19年

25

まあ、g ++を使用している場合は、このフラグを使用できます -Wunused

ドキュメントによると:

変数が宣言とは別に使用されていない場合、関数が静的に宣言されているが定義されていない場合、ラベルが宣言されているが使用されていない場合、およびステートメントが明示的に使用されていない結果を計算する場合は常に警告します。

http://docs.freebsd.org/info/gcc/gcc.info.Warning_Options.html

編集:これは他の便利なフラグです-Wunreachable-code ドキュメントによると:

このオプションは、コンパイラーがソースコードの少なくとも1行全体が実行されないことを検出したときに警告することを目的としています。

更新:類似したトピックであるレガシーC / C ++プロジェクトでデッドコード検出が見つかりました


4
これは、決して呼び出されない関数のプロトタイプのヘッダーをキャッチしません。または呼び出されないパブリッククラスメソッド。ローカルスコープの変数がそのスコープ内で使用されているかどうかのみを確認できます。
Falmarri、2011年

@Falmarriこのフラグを使用したことはありません。私はそれでどんな種類の死んだコードを見つけることができるのか自分自身を理解しようとしています。
UmmaGumma 2011年

-Wunused宣言されている(または宣言されて定義されている)変数について警告しますが、実際には使用されていません。ちなみにスコープ付きガードはかなり煩わしいです:p Clangには、(Ted Kremenekによって)書き込まれるが読み取られない不揮発性変数についても警告する実験的な実装があります。-Wunreachable-code到達できない関数内のコードについて警告します。たとえば、throwor returnステートメントの後にあるコード、または決して行われない分岐内のコード(トートロジー比較の場合に発生します)です。
Matthieu M.

18

コードカバレッジツールを探していると思います。コードカバレッジツールは、実行中のコードを分析し、実行されたコード行と実行されたコード行、および実行されなかったコード行を通知します。

このオープンソースコードカバレッジツールにチャンスを与えることを試みることができます:TestCocoon -C / C ++およびC#のコードカバレッジツール。


7
ここで重要なのは「実行中」です。入力データが一部のコードパスを実行しない場合、そのパスは使用済みとして認識されませんか?
シャープトゥース2011年

1
それは正しいです。コードを実行しないと、到達していない行を知る方法がありません。いくつかの通常の実行をエミュレートするためにいくつかの単体テストを設定するのはどれほど難しいでしょうか。
Carlos V

1
@drhishch私は、そのような未使用のコードのほとんどはコンパイラではなくリンカーを見つける必要があると思います。
UmmaGumma 2011年

1
@drhirsch確かに、コンパイラーは、宣言されているが呼び出されていない関数や一部の短絡評価など、到達できないコードの一部を処理できますが、ユーザーのアクションやランタイム変数に依存するコードはどうなりますか?
Carlos V

1
@golcarcol OK、void func()b.cppで使用されるa.cppに関数 があるとしましょう。どのようにコンパイラがチェックできるか、そのfunc()はプログラムで使用されていますか?それはリンカーの仕事です。
UmmaGumma 2011年

15

ここでの本当の答えは次のとおりです。

少なくとも、重要なケースでは、すべてを手に入れたかどうかはわかりません。到達不能コードに関するWikipediaの記事から、以下を検討してください。

double x = sqrt(2);
if (x > 5)
{
  doStuff();
}

ウィキペディアが正しく指摘しているように、賢いコンパイラーはこのようなものをキャッチできるかもしれません。しかし、変更を検討してください:

int y;
cin >> y;
double x = sqrt((double)y);

if (x != 0 && x < 1)
{
  doStuff();
}

コンパイラはこれをキャッチしますか?多分。しかし、それを行うにはsqrt、一定のスカラー値に対して実行するだけでは不十分です。それは(double)y常に整数になる(簡単)ことを理解し、sqrt整数のセット(のハード)の数学的な範囲を理解する必要があります。非常に洗練されたコンパイラーは、sqrt関数、またはmath.hのすべての関数、またはドメインが理解できる固定入力関数に対してこれを実行できる場合があります。これは非常に複雑になり、複雑さは基本的に無限です。洗練されたレイヤーをコンパイラに追加し続けることはできますが、特定の入力セットに到達できないコードに潜入する方法は常に存在します。

そして、決して入力されない入力セットがあります実際には意味をなさない、または他の場所で検証ロジックによってブロックされる入力。コンパイラがそれらについて知る方法はありません。

この結果、他の人が言及したソフトウェアツールは非常に便利ですが、後で手動でコードを実行しない限り、すべてを確実に把握できます。それでも、何も見逃していないことは決してわかりません。

唯一の真のソリューションであるIMHOは、可能な限り警戒し、自由に自動化を使用し、可能な場合はリファクタリングし、コードを改善する方法を常に模索することです。もちろん、とにかくそうすることをお勧めします。


1
真であり、デッドコードを残さないでください!機能を削除する場合は、不要なコードを削除してください。「念のため」にそのままにしておくと、(これまでに説明したように)後から見つけるのが困難な肥大化を引き起こすだけです。バージョン管理に屋の買いだめをさせましょう。
にオービットでライトネスレース

12

私自身は使用していませんが、cppcheckは未使用の関数を見つけると主張しています。それはおそらく完全な問題を解決しませんが、それは始まりかもしれません。


はい、参照されていないローカルの変数と関数を見つけることができます。
Chugaister 2013

うんcppcheck --enable=unusedFunction --language=c++ .、これらの未使用の関数を見つけるために使用します。
ジェイソンハリス

9

Gimple SoftwareのPC-lint / FlexeLintを使用してみてください。それは主張する

プロジェクト全体で未使用のマクロ、typedef、クラス、メンバー、宣言などを見つける

私はそれを静的分析に使用し、それが非常に良いことを発見しましたが、死んだコードを具体的に見つけるためにそれを使用しなかったことを認めなければなりません。


5

未使用のものを見つけるための私の通常のアプローチは

  1. ビルドシステムが依存関係の追跡を正しく処理することを確認してください
  2. 全画面のターミナルウィンドウを備えた2番目のモニターをセットアップし、ビルドを繰り返し実行して、最初の画面の出力を表示します。watch "make 2>&1"Unixではトリックを行う傾向があります。
  3. ソースツリー全体で検索と置換操作を実行し、各行の先頭に「//?」を追加します
  4. 「//?」を削除して、コンパイラによってフラグが付けられた最初のエラーを修正します 対応する行。
  5. エラーがなくなるまで繰り返します。

これはやや長いプロセスですが、良い結果が得られます。


2
メリットがありますが、非常に労働集約的です。また、関数のすべてのオーバーロードを同時にコメント解除することを確認する必要があります。複数のオーバーロードが該当する場合、優先度の低いものをコメント解除すると、コンパイルは成功しますが、プログラムの動作が不正になります(そして、関数が使用されます)。
j_random_hacker

最初のステップ(すべてのオーバーロード)で宣言のコメントを外すだけで、次の反復でどの定義が欠落しているかを確認します。そうすれば、実際に使用されているオーバーロードを確認できます。
Simon Richter、

@Simon:興味深いことに、メインの質問のコメントで、MSaltersは、呼び出されない関数の宣言の有無でも、オーバーロードの解決によって検出される別の2つの関数に影響を与える可能性があると指摘しています。確かに、これには非常に奇妙で不自然な設定が必要なので、実際には問題になることはほとんどありません。
j_random_hacker

4

コンパイルエラーを発生させずに、パブリック関数と変数をプライベートまたはプロテクトとしてマークします。これを行う際には、コードのリファクタリングも試みます。関数をプライベートにしてある程度保護することにより、プライベート関数は同じクラスからしか呼び出せないため、検索範囲が狭くなります(アクセス制限を回避するための愚かなマクロやその他のトリックがない限り、私はあなたをお勧めします新しい仕事を見つける)。現在作業中のクラスだけがこの関数を呼び出すことができるため、プライベート関数が不要であると判断する方がはるかに簡単です。この方法は、コードベースのクラスが小さく、疎結合である場合に簡単です。コードベースに小さなクラスがないか、結合が非常に緊密でない場合は、まずそれらをクリーンアップすることをお勧めします。

次に、残りのすべてのパブリック関数をマークし、コールグラフを作成して、クラス間の関係を把握します。このツリーから、ブランチのどの部分がトリミングできるように見えるかを調べてみてください。

この方法の利点は、モジュールごとに実行できることです。そのため、コードベースが壊れている場合でも、長期間テストを行わなくても簡単にユニットテストに合格できます。


3

Linuxをcallgrind使用している場合は、valgrindスイートの一部であるC / C ++プログラム分析ツールであるを調べることをお勧めします。このツールには、メモリリークやその他のメモリエラーをチェックするツールも含まれています(これらも使用する必要があります)。プログラムの実行中のインスタンスを分析し、そのコールグラフに関するデータと、コールグラフ上のノードのパフォーマンスコストに関するデータを生成します。これは通常、パフォーマンス分析に使用されますが、アプリケーションのコールグラフも生成するため、呼び出された関数とその呼び出し元を確認できます。

これは、ページの他の場所で言及されている静的メソッドを明らかに補完するものであり、完全に未使用のクラス、メソッド、および関数を排除するためにのみ役立ちます-実際に呼び出されるメソッド内のデッドコードを見つけるのに役立ちません。


3

私は実際にそのようなことをするツールを使用していません...しかし、私がすべての回答で見た限り、誰もこの問題が計算不可能であると言ったことはありません。

これはどういう意味ですか?この問題は、これまでコンピュータのアルゴリズムでは解決できないこと。この定理(そのようなアルゴリズムは存在しない)は、チューリングの停止問題の帰結です。

使用するすべてのツールはアルゴリズムではなく、ヒューリスティックです(つまり、正確なアルゴリズムではありません)。使用されていないすべてのコードを正確に提供するわけではありません。


1
私はOPが主にどこからも呼び出されない関数を見つけたいと思っていると思いますが、これは確かに計算不可能ではありません-最新のリンカはそれを行うことができます!最小限の苦痛と煩わしさでその情報を抽出するだけの問題です。
j_random_hacker

そうです、メインの質問に対する最後のコメントはありませんでした。ちなみに、実際には使われていないコードで参照されている関数があるかもしれません。そのようなことは検出されないかもしれません。
ギカゾイド、2011年

2

1つの方法は、デバッガーとコンパイラー機能を使用して、コンパイル中に未使用のマシンコードを排除することです。

一部のマシンコードが削除されると、デバッガーはソースコードの対応する行にbreakpojntを配置できなくなります。したがって、どこにでもブレークポイントを配置してプログラムを開始し、ブレークポイントを検査します。「このソースに対してコードがロードされていない」状態にあるものは、削除されたコードに対応します。これら2つのどちらが発生したかを見つけるための分析。

少なくともそれがVisual Studioではどのように機能するかであり、他のツールセットでもそれが可能だと思います。

これは大変な作業ですが、すべてのコードを手動で分析するよりも速くなると思います。


4
OPの質問は、コンパイルされたバイナリが効率的であることを確認することではなく、ソースコードのより小さくて管理しやすいサブセットを見つける方法に関するものだと思います。
j_random_hacker '27年

@j_random_hacker私はそれを与えました-そして、コードの除去は元のソースコードへの追跡に使用することさえできることがわかりました。
シャープトゥース2011年

それを達成するには、Visual Studioの特定のコンパイラフラグが必要ですか?そしてそれはリリースモードでのみ機能しますか、それともデバッグでも機能しますか?
Naveen、2011年

コンパイラーによって使用されているが最適化されている行についてはどうですか?
Itamar Katz

@Naveen:Visual C ++ 9では、最適化をオンにして/ OPT:ICFを使用する必要があります
シャープトゥース

2

CppDependは、未使用の型、メソッド、フィールドを検出することができ、さらに多くのことができる商用ツールです。WindowsとLinuxで利用できます(ただし、現在64ビットはサポートされていません)。2週間のトライアルが付属しています。

免責事項:私はそこでは働いていませんが、このツールのライセンス(および.NETコードのより強力な代替手段であるNDepend)を所有しています。

興味がある人のために、ここにCQLinqで書かれた死んだメソッドを検出するための組み込み(カスタマイズ可能な)ルールの例があります

// <Name>Potentially dead Methods</Name>
warnif count > 0
// Filter procedure for methods that should'nt be considered as dead
let canMethodBeConsideredAsDeadProc = new Func<IMethod, bool>(
    m => !m.IsPublic &&       // Public methods might be used by client applications of your Projects.
         !m.IsEntryPoint &&            // Main() method is not used by-design.
         !m.IsClassConstructor &&      
         !m.IsVirtual &&               // Only check for non virtual method that are not seen as used in IL.
         !(m.IsConstructor &&          // Don't take account of protected ctor that might be call by a derived ctors.
           m.IsProtected) &&
         !m.IsGeneratedByCompiler
)

// Get methods unused
let methodsUnused = 
   from m in JustMyCode.Methods where 
   m.NbMethodsCallingMe == 0 && 
   canMethodBeConsideredAsDeadProc(m)
   select m

// Dead methods = methods used only by unused methods (recursive)
let deadMethodsMetric = methodsUnused.FillIterative(
   methods => // Unique loop, just to let a chance to build the hashset.
              from o in new[] { new object() }
              // Use a hashet to make Intersect calls much faster!
              let hashset = methods.ToHashSet()
              from m in codeBase.Application.Methods.UsedByAny(methods).Except(methods)
              where canMethodBeConsideredAsDeadProc(m) &&
                    // Select methods called only by methods already considered as dead
                    hashset.Intersect(m.MethodsCallingMe).Count() == m.NbMethodsCallingMe
              select m)

from m in JustMyCode.Methods.Intersect(deadMethodsMetric.DefinitionDomain)
select new { m, m.MethodsCallingMe, depth = deadMethodsMetric[m] }

更新:Linuxの64ビットサポートがバージョン3.1に追加されました。
Roman Boiko

1

アプリケーションの作成に使用するプラットフォームによって異なります。

たとえば、Visual Studioを使用している場合、.NET ANTS Profilerなどのコードを解析およびプロファイルできるツールを使用できます。このように、コードのどの部分が実際に使用されているかをすばやく知る必要があります。Eclipseにも同等のプラグインがあります。

それ以外の場合で、アプリケーションのどの機能が実際にエンドユーザーによって使用されているかを知る必要があり、アプリケーションを簡単にリリースできる場合は、監査にログファイルを使用できます。

主な機能ごとに、その使用状況を追跡し、数日/週後にそのログファイルを取得して確認することができます。


1
.net ANTSプロファイラーはC#のように見えます-C ++でも動作しますか?
j_random_hacker 2011年

@j_random_hacker:私の知る限り、マネージコードで動作します。したがって、.NET ANTSは確かに「標準」のC ++コード(つまり、gccでコンパイルされた...)を分析できません。
AUS

0

自動的にできるとは思いません。

コードカバレッジツールを使用する場合でも、実行するには十分な入力データを提供する必要があります。

CoverityLLVMコンパイラなどの非常に複雑で高価な静的分析ツールが役立つ場合があります。

しかし、私は確信が持てず、手動のコードレビューを好むでしょう。

更新しました

まあ..未使用の変数を削除するだけで、未使用の関数は難しくありません。

更新しました

他の回答やコメントを読んだ後、それを行うことはできないと私は強く確信しています。

意味のあるコードカバレッジ測定を行うには、コードを知っている必要があります。カバレッジ結果の準備/実行/確認よりも多くの手動編集の方が速いことがわかっている場合。


2
あなたの答えの言い回しは誤解を招くものであり、LLVMに特別なことは何もありません...それは無料です!
Matthieu M.

手動編集は、プログラム内のロジックブランチを通過するランタイム変数の助けにはなりません。コードが特定の基準を満たしていないため、常に同じパスをたどっている場合はどうなりますか?
Carlos V

0

私は友人に本日この質問をしてもらい、私はいくつかの有望なClangの開発、たとえばASTMatcher静的アナライザーを見て回り、コンパイル中にデッドコードセクションを特定するための十分な可視性があるかもしれませんが、それから私はこれが見つかりました:

https://blog.flameeyes.eu/2008/01/today-how-to-identify-unused-exported-functions-and-variables

これは、参照されていないシンボルを識別する目的で設計されていると思われるいくつかのGCCフラグの使用方法のほぼ完全な説明です。


0

関数が呼び出される場合の一般的な問題はNP-Completeです。チューリングマシンが停止するかどうかわからないため、関数が呼び出されるかどうかを事前に一般的に知ることはできません。main()から作成した関数への(静的な)パスが存在する場合は取得できますが、それが呼び出されることは保証されません。


-3

まあ、g ++を使用している場合は、このフラグを使用できます。

ドキュメントによると:

Warn whenever a variable is unused aside from its declaration, whenever a function is declared static but never defined, whenever a label is declared but not used, and whenever a statement computes a result that is explicitly not used.

http://docs.freebsd.org/info/gcc/gcc.info.Warning_Options.html

編集:ここに他の有用なフラグがあります-Wunreachable-code一致するドキュメント:

This option is intended to warn when the compiler detects that at least a whole line of source code will never be executed, because some condition is never satisfied or because it is after a procedure that never returns.

6
この正確な情報は、現在の最高評価の回答ですでに言及されています。不要な重複を避けるために、既存の回答を読んでください。
j_random_hacker '27年

1
今、あなたはあなたのピアプレッシャーバッジを獲得することができます!
Andrew Grimm
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.