昨日のとおりすがり氏のコメントより
これでfdが型チェックにひっかからない辺りが……
型チェック、でもう一件ヒドイ目にあったのを思い出したのでその件について。
確か、その日も「なんだかよくわからないけど落ちるのでデバック手伝って」という指令を受けて死地へ向かった。動かしてみると確かに落ちる・・・のだが入力する値を適当に変えると落ちずに動く。とはいえ、予期してた結果とは全然異なる出力するから意味無いんだけど。
これもやはり気付けばなんてことなかったんだが、例によって気付くのにかなりの時間を要した。
以下、該当部分のコード。
hoge.cint hoge1(int foo, int var, int hoge) {...}
int hoge2(int foo, int var, int hoge) {...}
int hoge3(int foo, int var, int hoge) {...}
...
かなーーり状況を抽象化したコードにせざるを得ないんで申し訳ない。
重要なのは 2 点。関連する関数をいくらかまとめた hoge.c ということと、大抵の関数は int の引数を同数取るということ。要は、似たような外見をした関数がたくさん並んでる感じです。
で、こいつらを使う側は勿論
main_hoge.c
int main_hoge(int foo, int var, int hoge) {
int ret = hoge1(foo, var, hoge);
}
とこんな感じになるだが、落ちる場所はこんな風になっていた。
int ret = hoge10(foo, var, hoge);
渡される値 foo, var, hoge にも異常無し、コード上も全く問題無し。何が起こってるんだろうなぁ、と思ってたのだが、ふとシグネチャを見てみると・・・
int hoge10(int *foo, int var, int hoge) {...}
*foo!
なるほど、渡された値をポインタとして解釈してたのか・・・ってそりゃねぇよ。
当然コンパイル時に warning は出るのだが、プログラム自体がキャストを大量にする必要があることもあり、元々似たような warning が大量に出ていた。他の warning が出ている部分はとりあえず動いてるので無視したのがいけなかった。
warining には出すだけの意味があるのだと再確認した次第でした。
1、2、3 の次は何ですか?
もう一つの敗因として、hoge1、hoge2、hoge3、と似たようなシグネチャだから hoge10 もそうだろう、と思い込んだこと、になるかな。とはいえ、これは余りにもトラップ過ぎというか、なんというか。仕様書などを読んでみても、何故ここだけポインタ渡しなのかはわからないままでした。
並の人間であれば「1、2、3 の次は何ですか?」と問われれば当然「4」と答えると思う。可読性のくだりで、総称性・対称性・連続性という言葉が出てくるのは、人間は類推する点に立脚しているのだと考える。
しかし、バグ取りとなると状況はまったく逆になる。「1、2、3 の次は 100 です」とか平気でなるわけで、常識を捨て去らないとバグは取れない。「ここはそうなっているはず」「こうに違いない」・・・こういうのが大抵バグになってんだよなぁ。
・・・まぁ、今回のケースはそれ以前の問題のような気がしないでもないが・・・。