Takuro Ashie
ashie****@homa*****
2003年 11月 12日 (水) 05:03:14 JST
足永です. そろそろ言っておいた方が良いかな,と思うので,注意を促しておきます. zoeさんの書かれたコードは,コンパイル時にかなり多くの警告が出ます.gcc オプションに -Wall を付けて,これらの警告が出ないようにしておいたほう が良いと思います. コンパイラの警告というのは甘く見られがちですが,これはバグの可能性を事 前に指摘してくれる,とても偉い奴なのです.甘く見てはいけません. (コンパイルエラーは単なる文法エラー(typo)ですが,警告は「コンパイル段 階では判断がつかないけど,おそらく実行時に問題が出るコード」であって, 軽視すべきではありません.追求困難なバグに発展する可能性もあるという点 において,後者の方が重いバグであるとすら言えます) とりあえずヘッダがincludeされていない,使用されていない変数等の単純な 物は修正しておきましたが(ただし,後者はともかく前者については,場合に よって重大なバグをもたらします),2箇所ほど本当に問題のあるコードを発見 しました.これは実際に見て頂いた方が良いと思うので,そのままにしてあり ます. 一箇所目: src/net/kz-http.c の 369行目 もともとは strptime が未知の関数となっていたコードですが, #define __USE_XOPEN #include <time.h> を付け加える事によって関数の型が明確化され,真のバグが顕在化されました. kz-http.c: In function `kz_http_in_header': kz-http.c:369: warning: passing arg 3 of `strptime' from incompatible pointer type strptime は第3引数に struct tm * をとりますが,ここでは guint * 型の変 数を渡してしまっています.他の strptime を使っている箇所では問題が無い ので単純な勘違いだとは思いますが,このような勘違いを機械に発見してもら うためにも,インクルードすべきヘッダはしっかりとインクルードしておくべ きです. この場合,struct tm 型は guint 型よりもずっと大きく, strptime は struct tm 型の構造体に情報を書き込む関数ですから,他のメモリ領域(KzIO 構造体のfile_sizeメンバ以降)を破壊している可能性があります. 二箇所目: src/kz-downloader-group.c の 254行目 もともとは gtk_idle_add が未知の関数となっていたコードですが,これを g_idle_add に変更してバグが顕在化しました. kz-downloader-group.c: In function `kz_downloader_grp_remove_item': kz-downloader-group.c:254: warning: passing arg 1 of `g_idle_add' from incompatible pointer type g_idle_add や gtk_idle_add の第一引数は gboolean (*GSourceFunc) (gpointer data); と定義されていて,この関数の返り値で,繰り返すか繰り返さないかを決定し ます.ここでは繰り返してほしくはないわけですが,g_object_unref の返り 値は void として定義されているため,何が起こるかは不定です. (正常に動くかもしれないし,延々と g_object_unref を繰り返して他のデー タを破壊する可能性もある) この様な警告を無視していると,一見動いているように見えて,他のアーキテ クチャに持って行くと途端に動かなくなるなどの問題をしばしば引き起こしま す(そして開発者がその環境を持っていないため,解決困難なバグとなってし まう). この様な将来の無駄な苦労を事前に防ぐためにも,今,機械的に防ぐ事ができ るバグは,事前に修正しておく事が重要です.