『Cプログラミング診断室』目次次(第5章 管理は複雑に まとめ)

第5章 管理は複雑に

本当の恐怖


今までの説明でも、充分に「無知」な書き方であることは理解していただけ たでしょう。でも、本当の「恐怖」については、まだ説明していません。

似たようなものを2つ書き、その内容の整合性を確実に保つことは大変です。 もし、構造体

        struct  Panic {
                int     snoopy;
                int     charlie;
        };
があったとき、メンバーに double lucy; を追加しなければならなくなりまし た。もし、一方のソースファイル中で
        struct  Panic {   /* Panic(a) */
                int     snoopy;
                int     charlie;
                double  lucy;
        };
とし、別のソースファイル中で、
        struct  Panic {   /* Panic(b) */
                int     snoopy;
                double  lucy;
                int     charlie;
        };
としてしまったらどうなるでしょう。この2つの構造体はサイズが異なってし まいます。図5−2に、構造体のメモリレイアウトを示します。

図5−2 構造体Panicの構成

           panic(a)                         panic(b)

       +---------------+ - - - - - -  0 +---------------+       
       |  int snoopy   |                |  int snoopy   |
       +---------------+ - - - - - -  4 +---------------+
       |  int charlie  |                |///////////////|
       +---------------+ - - - - - -  8 +---------------+
       |               |                |               |
       +  double lucy  +             12 +  double lucy  +
       |               |                |               |
       +---------------+ - - - - - - 16 +---------------+
                                        |  int  charlie |
                         - - - - - - 20 +---------------+
                                        |///////////////|
                         - - - - - - 24 +---------------+

共に、

        struct  Panic   peanuts;
により、変数peanutsが確保されていても、このPanicがどちらのPanicかによっ て、本当のパニックが起こります。

Panic(a)の構造体を使って、変数peanutsの実体をメモリ上に確保し、Panic(b)による

    extern  struct  Panic  peanuts;
があるとき、peanuts.snoopyとpeanuts.lucyは偶然にも対応していますが、 peanuts.charlieは違っています。(b)の方で、peanuts.charlieに代入すると、 どういうことになるでしょう。(a)の方に実体があるのですが、構造体の定義 に(b)を使っているため、構造体の先頭から16バイトの位置から4バイト分が メンバーcharlieのためのメモリだと思って動作します。ということは、(a)に よって確保した実体(メモリ)の範囲を外れているので、もし(b)の方で charlieに代入をすると、変数peanutsに割り当てたメモリの次のアドレスに入っ ている変数を破壊してしまいます。

逆に、(a)側でcharlieに代入しても、そこは(b)ではパディングなので、 charlieの値は不変のままです。そして、これはなかなか見つけられないバグ になってしまいます。

つまり、知らない間に、誰かに、貴重なデータを破壊され、プログラムが動 作しなくなってしまうのです。メモリ上で偶然にも隣に配置された変数への代 入によって破壊されるのです。もちろん、破壊された変数を追っかけ回しても、 まず原因はつかめません。「誰かにデータを破壊された」ことは分かっても、 その誰かがなかなか分からないまま、仕事の予定がどんどん遅れていくのです。

■楽をしよう■

例では、構造体のメンバーが延々と並んでいましたね。あれだけ汚く並んで いるものを、きちんと対応づけるのは至難ですね。解決方法は、以上に述べた ことを実行して、「楽」をすればいいのです。

プログラムの信頼性を上げるには、プログラムを短くすることが一番です。 そして、ムダなファイルなど作らないことです。プログラムを全然書かなけれ ば、バグの入る余地など全くありません。「完璧」です。余分なプログラムを グダグダ書いたりするから、ノコノコとバグに入り込まれてしまうのです。だ から、いつも書いているように、「楽をする程、信頼度が向上」する訳です。 もう、この診断室の、座右の銘になっていますね。

そもそも、極めて似たものを、延々と作るなどというバカげた作業をしては いけません。そういう作業があったら、まず、「工夫はできないか」と考える べきです。あるいは、周りの優秀なプログラマに相談すべきです。何も言わず、 黙々とプログラムを書き続けている初心者がいたら、えてしてこのようなこと を延々としていることがあるので周りの人は注意しましょう。こういうバカな ことをして、会社の技術者のほとんどが、それがバカなことであるのに気付い ていないこともあり、気絶寸前になったこともあります。まあ、技術のない会 社は、有能なコンサルタントを見つけてください。何人もで、何ヵ月も掛かっ ても解決できなかった問題を、一瞬で解決してくれるかも知れません。

O'Reilly Japan刊

3/14発売
増刷:第3刷決定♪

オープンソース
Scheme言語処理系
Gaucheの愛好者団体

詳細はブログで



Copyright1996 Hirofumi Fujiwara. No reproduction or republication without written permission
『Cプログラミング診断室』目次次(第5章 管理は複雑に まとめ)