2012-10-25 22 views
13

私はいくつかのコードを書いて(すぐ)れたと誤ってscanf()で引数を反転:反転の引数()

char i[] = "ABC1\t"; 
scanf(i, "%s"); 

gcc -Werror -Wall -Wextraしてコンパイルすると、この1ビット文句はありません。明らかに、このコードは機能しませんが、なぜgccが引数を逆転したことを私に知らせませんでしたか? iがフォーマット文字列ではないこと、または2番目の引数がストア可能なタイプではないことを検出できませんか?

EDITすべての洞察力のための
おかげで、私は答えを見つけたように、これは「捕捉可能」

答えて

17

ハ!見つけた。 -Wformat=2フラグを付けてgccを押すと、それが捕捉されました。他人の参照のための情報投稿

は、ここで私は-Wallはそれがないている、それに-Wformatがあったが、まさに私について本当に重要な部分を想定していたlist of flags I found

-Wformat Check calls to printf and scanf, etc., to make sure that the arguments supplied have types appropriate to the format string specified...

ですfound:

-Wformat is included in -Wall. For more control over some aspects of format checking, the options -Wformat-y2k, -Wno-format-extra-args, -Wno-format-zero-length, -Wformat-nonliteral, -Wformat-security, and -Wformat=2 are available, but are not included in -Wall.

+0

ええ、+1私もそれを探していた。\ – Omkant

8

(下記参照用に掲載)を行う-Wformatフラグにひねり、私はそれを仮定があったルックスすべきではない。

int scanf (const char * format, ...); 

iが正常にconst char*に変換された、残りのすべてのパラメータは、単に「省略記号」であり、コンパイル時にチェックすることはできません。

+1

hea GCCが使用するdersは、通常、最初のパラメータが書式文字列としてマークされており、 '-Wformat'が提供されている場合、正しい型が残りのパラメータに確実に渡されます。私はこれが「壁」の一部だと信じています。 – Will

+1

@Willしかし、もう一度 - 非const char *がフォーマット文字列として渡されました(それはそれ自身で有効です)、コンパイラはパラメータチェックを強制しませんでした。書式文字列が 'const char *'またはリテラルであった場合は、そうしている可能性があります。 – Lyth

+0

おそらく、 'char * fmt'& 'const char * fmt'の間はチェックされません。 2番目の引数( "ABC \ t")がchar *またはconst char *になるかどうか誰にでも伝えられますか? – anishsane

3

のscanf(男性のscanf)のマニュアルエントリがプロトタイプを与える:

int scanf(const char *format, ...); 

のchar []のchar *のちょうど特別なタイプであるため、最初の引数が満たされます。二次的な引数は実行時に(私が思い出すと)評価されるので、ここではコンパイラによって考慮されません。コンパイラの将来的な見通しから、これはプロトタイプが与えられた関数への良い呼び出しです。

また、無効な場所に書き込もうとしているかどうかはコンパイラによって決して確認されません。 Cについての素晴らしい(またはひどい)ことは、あなたが望むものが多かれ少なかれ、あなたが望むものが悪いアイデアであっても、あなたにできるようにするということです。

+2

それ自身で 'scanf'がgccでコンパイルされ、glibcでgccでコンパイルされているのは事実ですが、scanfはパラメータが正しいことをコンパイラに知らせる' __attribute __((format(scanf、1、2)))これは 'scanf'の宣言によって強制されませんが。 – Shahbaz

関連する問題