Cに役立つGCCフラグ


157

設定を越えて-Wall、設定-std=XXX、その他の本当に便利な、あまり知られているコンパイラフラグは、Cでの使用のために何がありますか?

偶発的なタイプの不一致を完全に最小限に抑えるために、追加の警告や、場合によっては警告をエラーに変換することに特に興味があります。


9
さて-save-temps-Wshadowそして-fmudflapすべてのおかげで、私が知らなかった最大の発見でした。
マットジョイナー、

私の知る限りでは、コンテキスト:gcc -c [flags-go-here] -o myprog.o myprog.cCプログラムを(リンクではなく)コンパイルするために実行しています。
Rory O'Kane 2013年

回答:


64

-fコード生成オプションのいくつかは興味深いものです。

  • この-ftrapv関数は、符号付き整数オーバーフローでプログラムを中止させます(以前はCでは「未定義の動作」)。

  • -fverbose-asmでコンパイルし-Sてアセンブリの出力を調べる場合に便利です。これにより、有益なコメントが追加されます。

  • -finstrument-functions すべての関数のエントリポイントと終了ポイントでユーザー指定のプロファイリング関数を呼び出すコードを追加します。


-ftrapvこちらをご覧持ちですstackoverflow.com/questions/20851061/... ..長い固定を取得するために待っているバグがありますように思えます。
Arjun Sreedharan、2015

上記のコメントを確認できますか?
Suraj Jain

-ftrapvは、本質的に-fsanitize = signed-integer-overflowに置き換えられました。
Marc Glisse、2018

139

こちらが私のものです:

  • -Wextra-Wall:必須。
  • -Wfloat-equal:通常、浮動小数点数が等しいかどうかをテストすることは悪いので便利です。
  • -Wundef:初期化されていない識別子が#ifディレクティブで評価された場合に警告します。
  • -Wshadow:ローカル変数が別のローカル変数、パラメーター、またはグローバル変数をシャドウするとき、または組み込み関数がシャドウされるときは常に警告します。
  • -Wpointer-arith:関数またはのサイズに依存するものがあれば警告しvoidます。
  • -Wcast-align:必要なターゲットの配置が増加するようにポインターがキャストされたときに警告します。たとえば、整数が2バイトまたは4バイトの境界でのみアクセスできるマシンでにchar *キャストされた場合に警告しint *ます。
  • -Wstrict-prototypes:引数の型を指定せずに関数が宣言または定義されている場合に警告します。
  • -Wstrict-overflow=5:コンパイラーが符号付きオーバーフローが発生しないという前提に基づいて最適化する場合について警告します。(値5は厳しすぎる可能性があります。マニュアルページを参照してください。)
  • -Wwrite-strings:文字列定数に型のconst char[長さを与えると]、1のアドレスを非const char *ポインターにコピーすると警告が出ます。
  • -Waggregate-return:構造体または共用体を返す関数が定義または呼び出された場合に警告します。
  • -Wcast-qual:ターゲット型から型修飾子を削除するためにポインターがキャストされるたびに警告します*
  • -Wswitch-defaultswitchステートメントにdefault大文字と小文字の区別がない場合は常に警告します*
  • -Wswitch-enumswitchステートメントに列挙型のインデックスがありcase、その列挙の名前付きコードの1つ以上のfor がない場合は常に警告します*
  • -Wconversion:値を変更する可能性のある暗黙の変換について警告します*
  • -Wunreachable-code:コンパイラがコードが実行されないことを検出した場合に警告します*

*が付いているものは、誤った警告を出すことが多いので、必要に応じて使用します。


11
かなり完全なリストですが、もう1つ追加したいだけです。-Wformat=2:printf / scanf関数の追加のフォーマットチェック。
10

1
によって暗示されるこれらすべてを無視し-Wallますか?
chacham15 2012

2
@ chacham15、いや、そうは思いません。 gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Alok Singhal

1
@Alokうーん、多分それはディストリビューション間の標準ではありませんか?私のmbpでは、-Wwrite-strings嫌いなので明示的にオフにする必要があることはわかっています。
chacham15 2012

@ chacham15、たぶん。しかし、説明のために-Wwrite-strings、具体的には、それはの一部ではないと言う-Wallgcc.gnu.org/onlinedocs/gcc/...。多分あなたのセットアップの他の何かがそのフラグを設定していますか?または多分あなたはC ++をコンパイルしていますか?
Alok Singhal 2012

52

常に使用-O又は上記(-O1-O2-Os、など)。デフォルトの最適化レベルでは、gccはコンパイル速度を優先し、一元化された変数などについて警告するのに十分な分析を行いません。

-Werrorコンパイルを停止しない警告は無視される傾向があるため、ポリシーの作成を検討してください。

-Wall エラーである可能性が非常に高い警告をオンにします。

に含まれている警告は、-Wextra一般的で正当なコードにフラグを付ける傾向があります。これらはコードレビューには役立ちますが(lintスタイルのプログラムでは、より多くの落とし穴がより柔軟であることがわかりますが)、通常の開発ではオンにしません。

-Wfloat-equal プロジェクトの開発者が浮動小数点に慣れていない場合は良い考えですが、そうでない場合は悪い考えです。

-Winit-self便利です。なぜ含まれていないのかしら-Wuninitialized

-Wpointer-arithで動作しない大部分が移植可能なコードがある場合に便利です-pedantic


9
「-Wfloat-equalの+1は、プロジェクトの開発者が浮動小数点に慣れていない場合は良い考えであり、そうでない場合は悪い考えです。」特にその後半。:-)
R .. GitHub ICEのヘルプの停止

39
-save-temps

これにより、プリプロセッサとアセンブリの結果が残ります。

前処理されたソースは、マクロのデバッグに役立ちます。

アセンブリは、どの最適化が有効になったかを判断するのに役立ちます。たとえば、GCCが再帰関数の末尾呼び出しの最適化を行っていることを確認したい場合があります。これがないと、スタックがオーバーフローする可能性があるためです。


私はあなたがそれをどうやってそれを得たのか疑問に思っていました...私はいつもそれが必要ならアセンブリをダンプするようにgccにいつも頼みました

35

まだ誰もこれを言っていないことに驚いています-私にとって、最も有用なフラグ-gは、デバッグ情報を実行可能ファイルに入れて、デバッグしてソースをステップスルーできるようにすることです(熟練していてアセンブリを読んでいる場合を除く)stepi実行中のプログラムのコマンドのように)。


35

-fmudflap -UBをキャッチするためのすべての危険なポインター操作にランタイムチェックを追加します。これにより、プログラムは再びバッファオーバーフローを効果的に免疫化し、あらゆる種類のぶら下がりポインタをキャッチするのに役立ちます。

ここにデモがあります:

$ cat mf.c 
int main()
{
 int a[10];
 a[10]=1; // <-- o noes, line 4
}

$ gcc -fmudflap mf.c -lmudflap
$ ./a.out 
*******
mudflap violation 1 (check/write): time=1280862302.170759 ptr=0x7fff96eb3d00 size=44
pc=0x7f3a575503c1 location=`mf.c:4:2 (main)'
      /usr/lib/libmudflap.so.0(__mf_check+0x41) [0x7f3a575503c1]
      ./a.out(main+0x90) [0x400a54]
      /lib/libc.so.6(__libc_start_main+0xfd) [0x7f3a571e2c4d]
Nearby object 1: checked region begins 0B into and ends 4B after
mudflap object 0xf9c560: name=`mf.c:3:6 (main) a'
bounds=[0x7fff96eb3d00,0x7fff96eb3d27] size=40 area=stack check=0r/3w liveness=3
alloc time=1280862302.170749 pc=0x7f3a57550cb1
number of nearby objects: 1

うーん、mudflapはかなり厄介なようです:P
マットジョイナー

9
-fmudflapGCC 4.9以降はサポートされなくなりましたwarning: switch '-fmudflap' is no longer supported。これは、AddressSanitizerに置き換えられました。
Agostino

21

C / C ++にはあまり関係ありませんが、とにかく便利です:

@file

上記のすべてのフラグ(すべて指定したもの)を「ファイル」に入れ、この上記のフラグを使用して、そのファイル内のすべてのフラグを一緒に使用します。

例えば:

ファイル:compilerFlags

-壁

-std = c99

-ウェクストラ

次にコンパイルします:

gcc yourSourceFile @compilerFlags

15

-march=native コンパイルするプラットフォーム(=チップ)に最適化されたコードを生成する


2
ターゲットがわからない非ネイティブマシン用にコンパイルする場合は、命令セットを使用せずに最適化するmtune = xxxを使用できます。たとえば、mtune = genericは「平均的な」ケースのプロセッサーで最新の状態に保たれます。
-Turix

15

コンパイラーによって事前定義されているプリプロセッサー・フラグを知る必要がある場合:

echo | gcc -E -dM -

13

エラーの検出にはあまり役立ちませんが、ほとんど言及されていない-masm=intelオプションを使用すると、-Sすると、してアセンブリ出力を非常によく検査。

AT&Tアセンブリ構文は頭を痛めすぎます。


2
AT&TとIntelの違いは、C#とJavaの違いです。構文だけです。どちらもひどい。:)
マットジョイナー

2
+1 @michaelは、gccがひどいat&tではなくIntel構文を使用するようにします。アセンブリの検査は十分な脳サイクルを使用します-オペコードでdestする前にsrcが行く脳サイクルを無駄にする必要はありません。他のコンパイラのようにgccだけが__asm {}インラインをサポートする場合、これで準備は完了です!
greatwolf

10

私のメイクファイルには通常、

  CFLAGS= -Wall -Wextra -Weffc++ -Os -ggdb
  ...
  g++ $(CFLAGS) -o junk $<
  gcc $(CFLAGS) -o $@ $<
  rm -f junk

これらのオプションの中で最も重要なものは前に説明されているので、まだ指摘されていない2つの機能を指摘します。

私がいることをコードベースに取り組んでいるにもかかわらず、ニーズは、いくつかのプラットフォームへの移植のために通常のCであることをまだ何もまともなC ++コンパイラを持っていない、私は(Cコンパイラに加えて)C ++コンパイラで「余分な」コンパイルを行います。これには3つの利点があります。

  1. C ++コンパイラーは、Cコンパイラーよりも優れた警告メッセージを表示することがあります。
  2. C ++コンパイラーは-Weffc ++オプションを受け入れます。これにより、いくつかの便利なヒントが得られることがあります。これは、プレーンなCでのみコンパイルした場合は見逃してしまうでしょう。
  3. コードをC ++に比較的簡単に移植できるので、プレーンなCコードが無効なC ++コードであるいくつかの境界条件を回避できます( "bool"という名前の変数を定義するなど)。

はい、私は絶望的に楽観的なPollyannaです。1つのプラットフォームが廃止されたと宣言されるか、まともなC ++コンパイラーを手に入れられるようになると、今月は確実にC ++に切り替えることができます。私の心の中で、それは避けられない-唯一の問題は、それが経営陣が最終的に全員にポニーを発行する前または後に起こるかどうかです。:-)


それをC ++として書くことの良い点は、私はこれをよく考えます。(自然にサブセット)
マットジョイナー

6
CがC ++を支持して非推奨になっていることは決して起こらないことを指摘しておきます。申し訳ありません:)
Matt Joiner

4
rm -f junkではなく-o / dev / nullを検討してください
ulidtko

9
-Wstrict-prototypes -Wmissing-prototypes

10
そして-Wold-style-definition、プロトタイプの宣言であっても、K&Rスタイルの関数が良いアイデアだと考える再犯者に対処する必要がある場合。(私はそのような人々に対処する必要があります。K&Rで記述された新しいコードを見つけると、それは本当に私を困らせます。修正されていないレガシーK&Rのものを持っていることは十分に悪いですが、新しいコードです!Grump !!!)
Jonathan Leffler

9

これは言及されていない素晴らしい旗です:

-Werror-implicit-function-declaration

宣言される前に関数が使用されるときは常にエラーを出します。


8
man gcc

マニュアルは、良い説明で興味深い旗でいっぱいです。ただし、-Wallはおそらくgccを可能な限り冗長にします。もっと興味深いデータが必要な場合は、valgrindまたはその他のエラーチェックツールを確認してください。


1
ただし、loooooooooooooooooooooooooooooooongです。man gcc | nl11000行を超えるレポート。それは悪名高いbashマンページ以上のものです!
new123456 2011

12
彼らがそれをmanページに詰め込んだ神に感謝します。
Matt Joiner

6

まあ、それ-Wextraも標準的なはずです。-Werror警告をエラーに変換します(特になしでコンパイルした場合、非常に煩わしい場合があります-Wno-unused-result)。-pedanticと組み合わせると、std=c89C99機能を使用する場合に追加の警告が表示されます。

しかし、それはそれについてです。Cコンパイラを、C自体よりも型を節約できるものにチューニングすることはできません。


6

-M* オプションのファミリー。

これらを使用すると、cまたはc ++ソースファイルがどのヘッダーファイルに依存する必要があるかを自動的に判断するmakeファイルを作成できます。GCCはこの依存関係情報を含むメイクファイルを生成し、プライマリメイクファイルからそれらをインクルードします。

以下は、-MDと-MPを使用した非常に一般的なmakefileの例です。これは、c ++ソースファイルとヘッダーファイルでいっぱいのディレクトリをコンパイルし、すべての依存関係を自動的に把握します。

CPPFLAGS += -MD -MP                                         
SRC = $(wildcard *.cpp)                                                       

my_executable: $(SRC:%.cpp=%.o)                                                        
        g++ $(LDFLAGS) -o $@ $^                                               

-include $(SRC:%.cpp=%.d)

詳細については、次のブログ投稿をご覧ください。http//www.microhowto.info/howto/automatically_generate_makefile_dependencies.html


6

ある-Werrorすべての警告をエラーとして扱い、コンパイルを停止します、。gccマニュアルページには、お使いのコンパイラのすべてのコマンドラインスイッチについて説明します。


@マットジョイナー:使用しているマシンアーキテクチャについては言及しなかったので、gccフラグはあなたのものと誰かが示唆するリンクとでは異なる場合があります。このため、ソフトウェアにマニュアルページが付属しています。
グレッグヒューギル2010

4

-Wfloat-equal

差出人:http : //mces.blogspot.com/2005/07/char-const-argv.html

私が好む他の新しい警告の1つは-Wfloat-equalです。これは、等価条件で浮動小数点数を[持っている]ときに必ず警告します。それは素晴らしいです!コンピュータグラフィックスまたは(悪い:)計算ジオメトリアルゴリズムをすべてプログラムした場合、2つのフロートが同等に一致することはありません...


10
私のフロート、私がやっていることを知っているので、平等と一致しています。
Roland Illig、2010

4

特定の問題を修正するためのフラグを探しているこのスレッドを見つけました。ここには表示されないので、投稿で私を困らせていたものを追加します

-Wformat=2

-Wformat=> printfおよびへの呼び出しscanfなどをチェックして、指定されたフォーマット文字列に適切なタイプの引数が提供されていることを確認してください...

そしてそれについての本当に重要な部分(GCCマニュアルによると):

-Wformatに含まれてい-Wallます。形式チェックのいくつかの側面をより細かく制御するために、オプション-Wformat-y2k-Wno-format-extra-args-Wno-format-zero-length-Wformat-nonliteral-Wformat-security、および-Wformat=2利用可能ですが、-Wall.`に含まれていません

だから、あなたが持っているからと-Wallいって、すべてを持っているというわけではありません。;)


3

私は時々-sはるかに小さな実行可能ファイルを使用します:

-s
    Remove all symbol table and relocation information from the executable.

出典:http : //gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options


6
stripバイナリで実行する必要があります。これにより、デバッグ情報を含むバイナリを作成し、後で配布するために削除できます。
Hasturkun 2010

はい、strip動作しますが-s、実行ほど複雑ではありませんが、速くて簡単ですstrip
Vasiliy Sharapov 2010

3

この答えは少し話題から外れているかもしれませんが、質問は私からの価値ある+1です、なぜなら

偶発的なタイプの不一致を完全に最小限に抑えるために、追加の警告や、場合によっては警告をエラーに変換することに特に興味があります。
すべてのエラーと明らかではない可能性のあるエラーをキャッチするツールがあります。gccや他のコンパイラーと比較して、IMHOがエラーをキャッチするのに優れた働きをする副子があります。それはあなたの道具箱に持つ価値のある道具です。

スプリントなどのlintタイプのツールによる静的チェックは、コンパイラツールチェーンの一部である必要があります。


C:\ includeにプリプロセッサフ​​ァイルをファイルできないというエラーが常に表示されます。何をすべきか
わかり

2

追加の警告に特に興味があります。

に加えて-Wall-Wor -Wextraオプション(-W古いバージョンのgccだけでなく新しいバージョンのgccでも機能します。新しいバージョンでは代替名をサポートしています。-Wextraこれは同じ意味ですが、よりわかりやすくなっています)により、さまざまな追加の警告が有効になります。

これらのいずれによっても有効にされていない警告がさらにあります。使用可能なオプションのセットは、使用しているgccのバージョンによって異なります。詳細については、を参照するman gccinfo gccオンラインドキュメントを参照して、目的の特定のgccのバージョンを確認してください。また-pedantic、使用されている特定の標準に必要なすべての警告を発行します(-std=xxxまたは-ansi)などの他のオプションで、gcc拡張機能の使用について不平を言います。

偶発的なタイプの不一致を最小限に抑えるために、警告をエラーに変換する場合もあります。

-Werrorすべての警告をエラーに変えます。ただし、gccでは特定の警告に対して選択的にそれを行うことができないと思います。

-Werror外部ライブラリのヘッダーファイルがそれらの一部をトリップする可能性があるため、プロジェクトごとに有効にする警告(特にを使用する場合)を選択する必要があることに気付くでしょう。(-pedantic特に、私の経験では、この点で役に立たない傾向があります。)


4
「しかし、gccでは特定の警告に対して選択的にそれを行うことができないと思います。」実際、でできます-Werror=some-warning
Matthew Flaschen、2010

0
  • -Wmissing-prototypes:前のプロトタイプ宣言なしでグローバル関数が定義されている場合。
  • -Wformat-security:起こり得るセキュリティの問題を表すフォーマット関数の使用について警告します。現在、これは、フォーマット文字列が文字列リテラルではなく、フォーマット引数がない関数への呼び出しprintfscanf関数について警告します

0
  • -Werror=return-type:関数がgccに戻り値がない場合にエラーを強制します。それはある/we4716のVisual Studioで。

  • -Werror=implicit-function-declaration:定義されていない、または含まれていない関数を使用すると、エラーが発生します。それはある/we4013のVisual Studioで。

  • -Werror=incompatible-pointer-types:ポインターのタイプが予期されたポインタータイプと一致しない場合のエラー。それはある/we4133のVisual Studioで。

実際、私はCコードをクロスプラットフォームのままにしておきたいのですが、CMakeを使用し、提供されたcflagsを次のようにCMakeLists.txtに入れました。

if (CMAKE_SYSTEM_NAME MATCHES "Windows")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /we4013 /we4133 /we4716")
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration -Werror=incompatible-pointer-types -Werror=return-type")
endif()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.