設定-Wall
と設定-std=XXX
以外に、Cで使用するために、他に本当に役立つがあまり知られていないコンパイラフラグはありますか?
私は特に、追加の警告、および/または偶発的なタイプの不一致を完全に最小限に抑えるために警告をエラーに変えることに興味があります。
設定-Wall
と設定-std=XXX
以外に、Cで使用するために、他に本当に役立つがあまり知られていないコンパイラフラグはありますか?
私は特に、追加の警告、および/または偶発的なタイプの不一致を完全に最小限に抑えるために警告をエラーに変えることに興味があります。
これが私のものです:
-Wextra
、-Wall
:必須。-Wfloat-equal
:通常、浮動小数点数が等しいかどうかをテストするのは悪いので便利です。-Wundef
:初期化されていない識別子が#if
ディレクティブで評価された場合に警告します。-Wshadow
:ローカル変数が別のローカル変数、パラメーター、またはグローバル変数をシャドウするとき、または組み込み関数がシャドウされるときはいつでも警告します。-Wpointer-arith
:関数またはのサイズに依存するものがある場合は警告しますvoid
。-Wcast-align
:ターゲットの必要な配置が増加するようにポインタがキャストされるたびに警告します。たとえば、整数が2バイトまたは4バイトの境界でのみアクセスできるマシンでachar *
がキャストされた場合は警告します。int *
-Wstrict-prototypes
:引数の型を指定せずに関数が宣言または定義された場合に警告します。-Wstrict-overflow=5
:符号付きオーバーフローが発生しないという仮定に基づいてコンパイラが最適化する場合について警告します。(値5は厳しすぎる可能性があります。マニュアルページを参照してください。)-Wwrite-strings
:文字列定数に型のconst char[
長さを指定して、1つのアドレスを非ポインタ]
にコピーすると警告が表示されるようにします。const char *
-Waggregate-return
:構造体または共用体を返す関数が定義または呼び出された場合に警告します。-Wcast-qual
:ターゲット型から型修飾子を削除するためにポインタがキャストされるたびに警告します*。-Wswitch-default
switch
:ステートメントに大文字と小文字が含まれていないdefault
場合は常に警告します*。-Wswitch-enum
switch
:ステートメントに列挙型のインデックスがあり、case
その列挙の1つ以上の名前付きコードのaがない場合は常に警告します*。-Wconversion
:値を変更する可能性のある暗黙の変換について警告します*。-Wunreachable-code
:コードが実行されないことをコンパイラが検出した場合に警告します*。*のマークが付いているものは、誤った警告が多すぎることがあるので、必要に応じて使用します。
-f
コード生成オプションのいくつかは興味深いものです。
-fverbose-asm
アセンブリ出力を調べるためにコンパイルする場合に便利です-S
-いくつかの有益なコメントを追加します。
-finstrument-functions
すべての関数の入口と出口でユーザー提供のプロファイリング関数を呼び出すコードを追加します。
--coverage
gcov
プログラム内のブランチと呼び出しを計測し、カバレッジノートファイルを作成します。これにより、プログラムの実行時に、テストカバレッジの分析に役立つようにプログラムでフォーマットできるカバレッジデータが生成されます。
-fsanitize={address,thread,undefined}
AddressSanitizer、ThreadSanitizer、およびUndefinedBehaviorSanitizerコードサニタイザーをそれぞれ有効にします。これらは、実行時にさまざまな種類のエラーをチェックするためにプログラムを計測します。
以前、この回答にも言及されていましたが、この機能は、によって有効にされた消毒剤の1つに-ftrapv
取って代わられました。-fsanitize=signed-integer-overflow
-fsanitize=undefined
常に-O
以上(-O1
、、、-O2
など-Os
)を使用してください。デフォルトの最適化レベルでは、gccはコンパイル速度を重視し、単一化された変数などについて警告するのに十分な分析を行いません。
-Werror
コンパイルを停止しない警告は無視される傾向があるため、ポリシーの作成を検討してください。
-Wall
エラーである可能性が非常に高い警告をほぼオンにします。
に含まれる警告は、-Wextra
一般的な正当なコードにフラグを立てる傾向があります。それらはコードレビューに役立つかもしれませんが(lintスタイルのプログラムはより多くの落とし穴がより柔軟であることがわかりますが)、通常の開発ではそれらをオンにしません。
-Wfloat-equal
プロジェクトの開発者が浮動小数点に慣れていない場合は良い考えであり、慣れていない場合は悪い考えです。
-Winit-self
便利です。なぜ含まれていないのかしら-Wuninitialized
。
-Wpointer-arith
で動作しないほとんど移植可能なコードがある場合に便利です-pedantic
。
-save-temps
これにより、プリプロセッサとアセンブリの結果が残ります。
前処理されたソースは、マクロのデバッグに役立ちます。
このアセンブリは、どの最適化が有効になったかを判断するのに役立ちます。たとえば、GCCが一部の再帰関数で末尾呼び出しの最適化を行っていることを確認したい場合があります。これがないと、スタックがオーバーフローする可能性があります。
まだ誰もこれを言っていないことに驚いています-私に関する限り、最も有用なフラグは、-g
デバッグ情報を実行可能ファイルに入れて、デバッグしてソースをステップスルーできるようにすることです(アセンブリを熟知して読んでいる場合を除きます)。stepi
プログラムの実行中のコマンドのように)。
-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
C / C ++とはあまり関係ありませんが、とにかく便利です:
@file
上記のすべての適切なフラグ(すべて指定したもの)を「ファイル」に入れ、この上記のフラグを使用して、そのファイル内のすべてのフラグを一緒に使用します。
例えば:
ファイル:compilerFlags
-壁
-std = c99
-Wextra
次にコンパイルします:
gcc yourSourceFile @compilerFlags
-march=native
コンパイルするプラットフォーム(=チップ)用に最適化されたコードを生成する
コンパイラーによって事前定義されているプリプロセッサー・フラグを知る必要がある場合:
echo | gcc -E -dM -
エラーの検出にはあまり役立ちませんが、めったに言及されない-masm=intel
オプションを使用-S
すると、アセンブリ出力の検査がはるかに便利になります。
AT&Tアセンブリ構文は、頭を痛めすぎます。
これは言及されていない素晴らしい旗です:
-Werror-implicit-function-declaration
関数が宣言される前に使用されるときはいつでもエラーを出します。
私のmakefileには通常
CFLAGS= -Wall -Wextra -Weffc++ -Os -ggdb
...
g++ $(CFLAGS) -o junk $<
gcc $(CFLAGS) -o $@ $<
rm -f junk
これらのオプションの中で最も重要なものは以前に説明されているので、まだ指摘されていない2つの機能を指摘します。
適切なC++コンパイラがまだないプラットフォームへの移植性のためにプレーンCである必要があるコードベースに取り組んでいますが、C ++コンパイラ(Cコンパイラに加えて)を使用して「追加」コンパイルを行います。これには3つの利点があります。
はい、私は絶望的に楽観的なPollyannaであり、1つのプラットフォームが廃止されたと宣言されるか、まともなC ++コンパイラを取得し、最終的にC++に切り替えることができるようになると確信しています。私の考えでは、それは避けられないことです。唯一の問題は、経営陣が最終的に全員にポニーを発行する前か後かということです。:-)
-Wstrict-prototypes -Wmissing-prototypes
man gcc
マニュアルには、わかりやすい説明が付いた興味深いフラグがたくさんあります。ただし、-Wallはおそらくgccを可能な限り冗長にします。より興味深いデータが必要な場合は、valgrindまたはその他のエラーチェックツールを確認する必要があります。
-Werror
すべての警告をエラーとして扱い、コンパイルを停止するがあります。gcc
マニュアルページでは、コンパイラのすべてのコマンドラインスイッチについて説明しています。
まあ、-Wextra
標準でもあるはずです。-Werror
警告をエラーに変えます(これは、特になしでコンパイルする場合、非常に-Wno-unused-result
煩わしい場合があります)。-pedantic
と組み合わせると、std=c89
C99機能を使用する場合に追加の警告が表示されます。
しかし、それはそれについてです。CコンパイラをC自体よりも型を節約するものに調整することはできません。
-M*
オプションのファミリー。
これらを使用すると、cまたはc++ソースファイルが依存するヘッダーファイルを自動的に把握するmakeファイルを作成できます。GCCは、この依存関係情報を使用してmakeファイルを生成し、プライマリmakeファイルからそれらをインクルードします。
これは、-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
このスレッドが特定の問題を修正するためのフラグを探しているのを見つけました。ここには表示されないので、私の投稿で困惑していたフラグを追加します。
-Wformat=2
旗_
-Wformat
printf
=>やなどの呼び出しをチェックscanf
して、指定されたフォーマット文字列に適切な型が指定された引数を持っていることを確認します。
そしてそれについての本当に重要な部分(GCCマニュアルによると):
-Wformat
に含まれてい-Wall
ます。フォーマットチェックのいくつかの側面をより細かく制御するために、オプション-Wformat-y2k
、、、、、、-Wno-format-extra-args
およびが使用可能ですが-Wno-format-zero-length
、-Wallには含まれていません-Wformat-nonliteral
。-Wformat-security
-Wformat=2
だから、あなたが持っているからといって、-Wall
あなたがそれをすべて持っているという意味ではありません。;)
私は時々-s
、はるかに小さい実行可能ファイルに使用します。
-s
Remove all symbol table and relocation information from the executable.
ソース: http: //gcc.gnu.org/onlinedocs/gcc/Link-Options.html#Link-Options
-Wfloat-equal
差出人:http ://mces.blogspot.com/2005/07/char-const-argv.html
私が好きな他の新しい警告の1つは、-Wfloat-equalです。これは、等式条件で浮動小数点数を[持っている]ときはいつでも警告します。それは素晴らしいです!コンピュータグラフィックスまたは(さらに悪い:)計算幾何学アルゴリズムをすべてプログラムした場合、2つのフロートが同等に一致することはないことを知っています...
この答えは少し話題から外れているかもしれませんが、質問は私からの価値のある+1です。
私は特に、追加の警告、および/または偶発的なタイプの不一致を完全に最小限に抑えるために警告をエラーに変えることに興味があります。明らかではないかもしれないすべてのエラーと潜在的なエラーをキャッチする必要があるツールがあります。IMHOがgccや他のコンパイラと比較してエラーをキャッチするのにはるかに優れた仕事をするスプリントがあります。それはあなたの道具箱に持っている価値のある道具です。
スプリントなどのlintタイプのツールを介した静的チェックは、コンパイラツールチェーンの一部である必要があります。
私は特に追加の警告に興味があります、
に加えて-Wall
、-W
or-Wextra
オプション(-W
古いバージョンのgccと新しいバージョンで機能します。新しいバージョンは代替名-Wextra
をサポートします。これは同じことを意味しますが、より説明的です)、さまざまな追加の警告を有効にします。
また、一般的にもっと疑わしいほど悪いものに対して、これらのどちらによっても有効にされない警告がさらにあります。使用可能なオプションのセットは、使用しているgccバージョンによって異なります。詳細については、man gcc
またはinfo gcc
詳細を参照するか、関心のある特定のgccバージョンのオンラインドキュメント-pedantic
を参照してください。また、使用されている特定の標準で必要なすべての警告を発行します(-std=xxx
または)などの他のオプション-ansi
については、gcc拡張機能の使用について不平を言います。
および/または偶発的なタイプの不一致を完全に最小限に抑えるために、場合によっては警告をエラーに変換します。
-Werror
すべての警告をエラーに変えます。ただし、gccでは特定の警告に対して選択的にそれを実行できるとは思いません。
-Werror
外部ライブラリからのヘッダーファイルがそれらの一部をトリップする可能性があるため、プロジェクトごとに有効にする警告を選択する必要があることに気付くでしょう(特にを使用する場合)。(-pedantic
特に、私の経験では、この点では役に立たない傾向があります。)
-Wmissing-prototypes
:グローバル関数が事前のプロトタイプ宣言なしで定義されている場合。-Wformat-security
:セキュリティ上の問題の可能性を表すフォーマット関数の使用について警告します。現在、これは、フォーマット文字列が文字列リテラルではなく、フォーマット引数がない関数の呼び出しprintf
と関数について警告しますscanf
-Werror=return-type
:関数がgccに戻り値を持たない場合にエラーを強制します。VisualStudioにあり/we4716
ます。
-Werror=implicit-function-declaration
:関数が定義されていない/含まれていない場合にエラーを強制します。VisualStudioにあり/we4013
ます。
-Werror=incompatible-pointer-types
:ポインタの型が予想されるポインタの型と一致しない場合は、エラーが発生します。VisualStudioにあり/we4133
ます。
実際、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()