何となく Blog by Jitta
Microsoft .NET 考

目次

Blog 利用状況
  • 投稿数 - 761
  • 記事 - 18
  • コメント - 36196
  • トラックバック - 222
ニュース
  • IE7以前では、表示がおかしい。div の解釈に問題があるようだ。
    IE8の場合は、「互換」表示を OFF にしてください。
  • 検索エンジンで来られた方へ:
    お望みの情報は見つかりましたか? よろしければ、コメント欄にどのような情報を探していたのか、ご記入ください。
It's ME!
  • はなおか じった
  • 世界遺産の近くに住んでます。
  • Microsoft MVP for Visual Developer ASP/ASP.NET 10, 2004 - 9, 2011
広告

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

その他

わんくま同盟

同郷

 

ウェブ コミュニティでの、私のスタンス。

「答えを教えろ。じゃなきゃ、応えるな。」って人も、中には居ます。

私が答えを教えず、理解して欲しいのには、理由があります。それは、答えを教えて、私が困ったことがあるから。

先のエントリ、「オブジェクトって、おいしい?」の「よく知らない人のコード例」は、本当の話から作ったものなのです。

あちらでの話の都合上、あちらには載せられなかったことです。コードを再掲。

配列から構造体にコピーする

{ ...略 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
コメント
  • # re: 答えは教えない。理解して欲しい。
    774RR
    Posted @ 2007/07/30 8:36
    本題と異なるところにのみツッコミを入れてみるテスト

    strdup はご存じなかったですか、そうですか。
    calloc はご存じなかったですか、そうですか。

    C では NULL は ((void*)0) であることが許容されているので
    > if (ret == NULL) { exit(-1); }
    こっちはまったくもって疑問の余地無く完璧に正しいですが
    > memset(ret, NULL, sz);
    こっちは俺んちの vc++ が C4027 の文句を言いますです。

    あといきなり exit っつーのは無謀系ですな。
    俺なら現コードを全部捨てて C++ に移行し string 系を使いたいです。
  • # re: 答えは教えない。理解して欲しい。
    Craf
    Posted @ 2007/07/31 1:06
    気になったのは
    >数日後、コードを見せてもらうと
    彼は数日間一度も実行しないでコードを書いてたのでしょうか。
    http://blogs.yahoo.co.jp/hyuki0000/9033095.html
    方向が違うけどこの話を思い出してしまいました。
  • # re: 答えは教えない。理解して欲しい。
    Jitta
    Posted @ 2007/07/31 7:29
    あ、復旧してる。お疲れ様です〉中さん

    長文になるので、夜、PCから返事します。
  • # re: 答えは教えない。理解して欲しい。
    Jitta
    Posted @ 2007/07/31 22:00
    774RRさん、コメントありがとうございます。

     知っているから使う、知らないから使わない(いや、使えないだけど)は、ちと違います。
     本当のところ、strdup の存在は忘れていましたが、忘れているというとは使ってこなかったわけで、これからも使わないでしょう。理由は簡単。allocate していることがわかりにくいからです。だから、allocThenCopy なのです。これだと、アロケートしていることが名前で解るでしょ?strdup だと、strcpy などに埋もれてしまいそうだから、たぶんこれからも使わない。
     calloc も、知っていますが、使いません。何でだっただろう?サイズ計算はやってくれるから楽なんだよな。でも、使わないことにしています。realloc を使わないのは、何でだっただろう?面倒だったから、のような気がする(^o^;


     そういえば、memset に NULL 使うと、warning が出てましたねぇ。0に置き換えた記憶が、かすかにある...lint だっけ?オプションが決まってて、「このオプションでワーニングが出ないこと」って規約になってて。あるバージョン(たぶん、ANSI 対応)からボロボロ出てきて、困った困った。


     いきなり exit。。。やめたい、というか、、、「いきなり exit はまずいから、エラー返して適切に終了処理するようにしておいてね。」と、言っておいたんですけどねぇ。。。理解したのか、面倒だからしなかったのか。。。ここも、サンプルを提供してしまったことの悪影響です。直す気力もなく(私も他の仕事を抱えていたので)、直す気もなさそうなので(なんせ、時間がおしていたので)、見て見ぬふりを決め込みました。もっと早く見ていれば、手を入れたのですが、まぁ、後の祭りってことで。


    > 俺なら現コードを全部捨てて C++ に移行し string 系を使いたいです。
    そうしたい。
    というか、そうしたかったことを思い出して、http://blogs.wankuma.com/jitta/archive/2007/07/26/87218.aspx のエントリで、あっちで書かなかった、「いったい何があったの?」ってのが、このエントリ。


    Crafさん、コメントありがとうございます。

    > 彼は数日間一度も実行しないでコードを書いてたのでしょうか。
    いえ、私が聞かなかったのが、まずかったのでしょう。一生懸命、直そうとしていたようです。いろいろ、継ぎ接ぎされた跡がありましたから。
    しかし。。。デバッグオプションつけずにコンパイルするものだから、、、いや、もう、思い出したくない。。。
  • # re: 答えは教えない。理解して欲しい。
    Craf
    Posted @ 2007/08/01 1:51
    >理由は簡単。allocate していることがわかりにくいからです。だから、allocThenCopy なのです。これだと、アロケートしていることが名前で解るでしょ?
    strdupのネーミングがわかりづらいのは同意ですが、標準関数をわざわざ再作成するのは悪だと思います。
    標準なんだから世の中のソースではいくらでも使われてるわけで、わかりにくいから…ってのはなんか違うかと。
    まぁstrdupの場合はANSI標準ではなくデファクトスタンダードなので微妙なとこですが。

    それはともかく、この話に関しては、単なる上司と部下のコミュニケーション不足の例と読めてしまいました(^^;
    コミュニティでのスタンスって話とのつながりがいまいち納得いかなかったり。
  • # re: 答えは教えない。理解して欲しい。
    774RR
    Posted @ 2007/08/01 10:04
    strdup デファクトスタンダードって言うなー
    SVID スタンダードだぞっぷんぷん

    標準関数と同一の機能の関数を自前で実装する、ってのは
    練習としてはありかもしれないけど製品に使うのは却下。
    処理系ベンダが用意した関数のほうがたいてい高速だったりするので。
    AllocThenCopy は中で strlen を2回も呼んでるのが論外。
    第二引数が const char * でないのはご愛嬌?でも俺的には却下。
  • # re: 答えは教えない。理解して欲しい。
    通りすがり
    Posted @ 2007/08/01 12:55
    <引用>
     そういえば、memset に NULL 使うと、warning が出てましたねぇ。0に置き換えた記憶が、かすかにある...lint だっけ?オプションが決まってて、「このオプションでワーニングが出ないこと」って規約になってて。あるバージョン(たぶん、ANSI 対応)からボロボロ出てきて、困った困った。
    </引用>

    困ってないで、なぜmemsetの第二引数にNULLを使ってはいけないのかを調べましょう。
  • # re: 答えは教えない。理解して欲しい。
    やれやれ
    Posted @ 2007/08/01 17:22
    説得力なさすぎな気がする。
    俺は理解してないけど理解しない奴はだめってどういうこと?
  • # re: 答えは教えない。理解して欲しい。
    rafinn
    Posted @ 2007/08/02 2:53
    「答えを教えろ。じゃなきゃ、応えるな。」は「答えは教えない。理解して欲しい。」に対する拒絶反応のケースが多いようにも見えます。
  • # re: 答えは教えない。理解して欲しい。
    ラフィン
    Posted @ 2007/08/02 2:54
    「答えを教えろ。じゃなきゃ、応えるな。」は「答えは教えない。理解して欲しい。」に対する拒絶反応のケースが多いようにも見えます。
  • # ユトリストの驚異(脅威から変更)
    何となく Blog by Jitta
    Posted @ 2007/10/05 22:14
    ユトリストの驚異(脅威から変更)
タイトル
名前
Url
コメント