- blogs:
- cles::blog
scanf() で整数を 1 バイト分だけ読み取る
c最近の gcc はチェックが厳しくなっているので scanf()
を使って int の値を char に書込むと *** stack smashing detected ***
というエラーが出るようです。
例えば 10 進の値を char に代入するようなプログラムは C 言語の入門などでよく出てきます。
test.c
† コンパイルすると警告が出る
これを単純にコンパイルすると、以下のように警告が出ます。
これを見て驚くのは、最近の gcc はエラーや警告メッセージがかなり丁寧になっているということ。
これをきちんと読めば、scanf()
に含まれる書式指定 %d
は可変長引数部分の int *
に対応していなければならないのに対して、実際の可変長引数部分の型は char *
になっているので、型があっていないというのがきちんと分かります。
これを修正するための候補として %hhd
も挙げられていますね。
† とりあえず無理やり実行してみる
とりあえずコンパイル自身はされているので、警告を無視して実行してみます。
結果は表示されますが、実行時エラーが出て正常終了しません。
実行時のエラーの原因は char (1B) の領域に無理やり int (4B) 分のデータを書込んでしまうからですね。
要はバッファーオーバーフローです。
このバッファオーバーフローが gcc の stack protector*1 によって検知されていることになります。
実行結果が表示されてしまっているのは、stack protector が関数の実行後(今回の場合は main()
の実行終了時 )にバッファオーバーフローを検出しているためです。
† 書式を修正してみる
gcc の警告のアドバイスに従って書式を %hhd
にしてみるとコンパイルの警告、実行時エラー共に解消しました。
サイズ的には %d
→4B、%hd
→2B、%hhd
→1B となるようなので、h
は half の h
でしょうか(l
は longの l
だと分かるのですが)。
test.c
ちなみに調べてみたら h
接頭辞は C99 から使えるようになっていたようです。
このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/12934
古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
コメントは承認後の表示となります。
OpenIDでログインすると、即時に公開されます。
OpenID を使ってログインすることができます。
- シャープの空気清浄加湿器の... (1)
- SMARTEK デジタル温湿度計 (1)
2 . Word で数式がグレーアウトされていて挿入できないときは(15133)
3 . awk で指定した n カラム目以降を出力する(11738)
4 . アーロンチェアのポスチャーフィットを修理(11420)
5 . Windows 10 で勝手にログアウトされないようにする(9718)