ウェブ コミュニティでの、私のスタンス。
「答えを教えろ。じゃなきゃ、応えるな。」って人も、中には居ます。
私が答えを教えず、理解して欲しいのには、理由があります。それは、答えを教えて、私が困ったことがあるから。
先のエントリ、「オブジェクトって、おいしい?」の「よく知らない人のコード例」は、本当の話から作ったものなのです。
あちらでの話の都合上、あちらには載せられなかったことです。コードを再掲。
{
...略
list2 = (PChainList) myalloc(sizeof(ChainList));
for (int i = 0; i < count; i++) {
PChainList next;
next = (PChainList) myalloc(sizeof(ChainList));
allocThenCopy(&next->name, データ配列[i]);
allocThenCopy(&next->city, データ配列[i]);
strcpy(next->phone, データ配列[i]);
next->age = atoi(データ配列[i]);
next->next = list2;
list2 = next;
}
...略
}
void allocThenCopy(char** dst, char* src)
{
*dst = (char*) myalloc(strlen(src) + 1);
memcpy(*dst, src, strlen(src));
}
void* myalloc(unsigned int sz)
{
void* ret = malloc(sz);
if (ret == NULL) { exit(-1); }
memset(ret, NULL, sz);
return ret;
}
こんな形で渡しました。「読み込んだものを構造体に入れたから、妥当性チェックをしてから処理して」と。数日後、コードを見せてもらうと、こんな風に作ってありました。
{
...略...
for (PChainList l = list2; l != NULL; l = l->next) {
if (nameの検査1 == FALSE) {
allocThenCopy(&l->name, "の設定値が異常です。");
goto write_log;
} else if (nameの検査2 == FALSE) {
allocThenCopy(&l->name, "の設定値が異常です。");
goto write_log;
} else ...略... {
...略...
}
...略...
continue;
write_log:
...略...
}
...略...
}
「C で文字列を扱うのは、ちょっと難しいから。必ず格納できるだけの場所を用意してから格納して。使い終わったら free して。」とは言ってあります。「でも、面倒だから、allocThenCopy ってのを作ったから。第2引数がコピーできるだけを大きさを確保して、コピーするから。第1引数は、使い終わったら free してね。」と渡したんだけど。。。
「ここのエラー メッセージなんやけど、どんなメッセージ出すんやったっけ?」
「えっと..."nameの設定値が異常です。"です。」
「そうやんな。name って、実際に指定してあるのを出すんやんな?」
「はい、そうです。」
「ふ~ん。。。」
これ、文字列連結やないねん!!
「これ、こういう用途で使うために用意したものじゃないんだけど?」
「え?そうなんですか?いけないのですか?」
「だって、allocate してコピーって書いてあるやん。コード見た?右の引数分だけの領域を用意して、全部コピーすんねん。左は、以前何があったか関係なく、ほかすから。これやと、リークしてまう。」
「そうなんですか。」
と、allocThenCopy を修正しようとした。
「ちょっと待って、なんでこれ修正するん?」
「後ろに追加すると思って作っているので、たくさんあるんですよ。全部修正していたら間に合いませんから。」
「そんなことしたら、今コードが書いてある用途で使っているところ、書き直さなあかんやん!」
「そんなところありませんから。」
「おまえが使とらんでも、オレが使とんじゃ!!」
いったい、どんなコード書いてきたんだろう?全部書き直したくなった。。。
もちろん、処理をするための情報が書いてあるものを、処理をした結果に書き直そうとしている。意味がまったく変わってしまうので、そんなことをしてはいけない。それも「時間がないので」って。。。
妥当性チェックも、その前に「処理の単位があるでしょ。この場合、ファイルを読み込むところ、読み込んだものを構造体に変換するところ、構造体のデータが正しいかチェックするところ、実際に処理をするところ、というような。この単位で、関数を分けて欲しい。」という話をしています。if 文のブロックを関数に追い出してあれば、goto 文も不要になるし、同じエラー メッセージを複数回書く必要もありません。そこまで説明して、「分けてね」と言ったんだけどなぁ。。。
時間がないことを理由に、理解することより解決することを優先したツケのようですorz
投稿日時 : 2007年7月28日 21:36