printf with size_t (in C) | Chandler@Berlin

Chandler@Berlin

ベルリン在住

size_t を printf で使う場合,32bit と 64bit で問題であるのは

http://www.mpi-inf.mpg.de/~hitoshi/otherprojects/tips/bugs/articles/11printftrap.shtml

という page にもある.環境によっては出力が正しくないだけではなく,一文字の typo で crash も可能というのが恐しいことである.特にこの Page の条件では compiler の warning も出てこないので深刻である.

結論としては stream を使えばこの問題自体が生じないのでよほど巨大なデータを使うとか以外では printf 系は使わない方が良いだろう.

この問題に関して,ではなぜ float と double ではどちらも %f や %g で問題がないのかという疑問を同僚から尋ねられた.

これは size_t が環境によっては 32 bit の場合と 64 bit の場合があり,printf は format の文字列を信じてメモリを操作(va_args)するので,format 文字列に間違いがあると問題が発生することに起因する.であれば,float とdouble という 32bit と 64bit をなぜ同じ %f で出力指定して問題が置きないのであろうか.

これは C 言語では va_arg では promotion ということが自動で起きているからである.va_arg の関数が呼ばれる場合には char は int に,float は doubleに promotion が起こって関数が呼ばれる.つまり float は double に変換されて関数が呼ばれるために float と double の違いは吸収されるのである.実はK & R 本の va_arg の例題に既にこの話はあるのだが,ちゃんとした話は OpenBSD の va_arg のマニュアルかhttp://www.openbsd.org/cgi-bin/man.cgi?query=va_arg,gcc の Calling Variadic Functions
(http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_28.html) をみ
ると良い.

しかし結論はやっぱり同じであり,できれば stream にした方が良い.問題がそもそも起きないようにするべきだと思うのである.

なぜこんなことを書いているかと言うと,3ds*** という DCC software がある条件で crash するのは,この一文字のタイプミスが原因だからだった.私はそもそも上記の結論に従っているので私が書いたのではないが,誰かがこういう間違いをしたのを,私が debug しなくてはいけないのである.でも私は仕事だからまだいいけれども,お金を払ったお客さんは,これが原因でシーンやイメージや費した時間が一瞬で消えていくのを見たら,怒り心頭なのではないかというのが心配なのである.開発者としては大きな声で言うべきではないようなのだが,できれば,次のバージョンでは新しい機能がどうこう,というよりも,個人的にはより安定してクラッシュしにくいものをリリースしたい.しかし,上司達が言うには言うには,不安定でも新機能がなければお客さんは我々のソフトには見向きもしないということなので,それを信じて仕事をしているのが現状である.確かに宣伝でも新機能が主なところを見るとそういうお客さんが多いのが現状なのかもしれない.